您好我正在使用下面的查询从每个唯一对话中选择最新消息。除非我尝试整合INNER JOIN
以尝试将用户的user_id
与username
表格中的users
相关联,否则一切都会完美无缺。
我已经尝试了几乎所有组合来集成INNER JOIN
所以我决定将它与工作查询分开,直到我得到帮助。
我做了一个小提琴 http://sqlfiddle.com/#!9/a9bbc/1我只想让右边的user_id打印用户的用户名
SELECT message_id,
msg,
user_id
FROM messages
JOIN (SELECT user_id,
Max(dat) m
FROM ((SELECT message_id,
recipient_id user_id,
dat
FROM messages
WHERE owner_id = 1)
UNION
(SELECT message_id,
owner_id user_id,
dat
FROM messages
WHERE recipient_id = 1)) t1
GROUP BY user_id) t2
ON ( ( owner_id = 1
AND recipient_id = user_id )
OR ( owner_id = user_id
AND recipient_id = 1 ) )
AND ( dat = m )
ORDER BY dat DESC
users.username INNER JOIN users ON messages.user_id = users.user_id;
答案 0 :(得分:1)
我认为这是正确的......最后。不存在在开始后过滤掉响应。内部查询抓取最近的对话。这应该与预期的输出相匹配。
SELECT dT.maxid AS message_id
,(SELECT msg FROM messages M WHERE M.message_id = dT.maxid) AS message_id
,(SELECT username FROM users U WHERE U.user_id = dT.owner_id) AS user_id
FROM (
SELECT MAX(message_id) as maxid
,owner_id
,recipient_id
FROM messages M
GROUP BY owner_id, recipient_id
) AS dT
WHERE NOT EXISTS(SELECT *
FROM messages M2
WHERE M2.recipient_id = dT.owner_id
AND M2.owner_id = dT.recipient_id
AND M2.message_id > dT.maxid)
ORDER BY dT.maxid
产生输出:
message_id message_id user_id
8 you should Now see this instead even with the User2
owner_id flipped.. The users_id in the query is 1
and it gets the conversation with user_id 2
9 You should also see this User1
答案 1 :(得分:1)
如果messages.message_id
是AUTO_INCREMENT PRIMARY KEY
列,这可能是获得所需结果的最快方式:
select m.message_id, m.msg, u.username,
case sub.other_user_id
when m.owner_id then 'received from'
when m.recipient_id then 'sent to'
end as direction
from (
select other_user_id, max(message_id) as message_id
from (
select recipient_id as other_user_id, max(message_id) as message_id
from messages
where owner_id = @uid
group by recipient_id
union all
select owner_id as other_user_id, max(message_id) as message_id
from messages
where recipient_id = @uid
group by owner_id
) sub
group by other_user_id
) sub
join messages m on m.message_id = sub.message_id
join users u on u.user_id = sub.other_user_id
order by sub.message_id desc
我还添加了专栏direction
。这样您就可以知道消息是否已发送或接收。结果如下:
| message_id | msg | username | direction |
|------------|------------------------------------------------------------------|----------|---------------|
| 9 | You should also see this | User3 | sent to |
| 8 | you should Now see this instead even with the owner_id flipped.. | User2 | received from |
http://sqlfiddle.com/#!9/a9bbc/34
请注意,您仍然可以在SELECT子句中的users
和messages
表中添加任何列。
要让此查询快速运行,您需要messages(owner_id, recipient_id)
和messages(recipient_id, owner_id)
上的索引。
答案 2 :(得分:0)
当你加入任何表或子查询时,你真的真的需要包含所有列引用的表名或表别名。我将最大数据更改为maxdat,因此我可以使用m作为消息。
declare @oq nvarchar(max) = N'prefix_'
declare @cmd nvarchar(max)
select @cmd = a from (
select 'EXEC sp_rename ''' + TABLE_NAME + ''', ''' + REPLACE(TABLE_NAME, @oq, N'') + ''' '
from INFORMATION_SCHEMA.TABLES
for xml path('')
) t(a)
exec sp_executesql @cmd
答案 3 :(得分:0)
如果我理解正确,您需要发送或收件人为“1”的最新邮件以及相关的用户名。
这表明:
SELECT
m.message_id
, m.msg
, m.user_id
FROM messages m
JOIN (
SELECT
user_id
, MAX(dat) maxdat
FROM (
(SELECT
message_id
, recipient_id user_id
, dat
FROM messages
WHERE owner_id = 1)
UNION
(SELECT
message_id
, owner_id user_id
, dat
FROM messages
WHERE recipient_id = 1)
) t1
GROUP BY
user_id
) t2 ON (
(m.owner_id = 1 AND m.recipient_id = t2.user_id)
OR (m.owner_id = t2.user_id AND m.recipient_id = 1)
)
AND (m.dat = t2.maxdat)
ORDER BY
m.dat DESC
编辑:
基于您的SQL Fiddle,上述理解不正确。你想考虑成对的收件人,所以我想你想要:
select m.*, ur.username as recipient_name, us.username as sender_name
from messages m join
users ur
on m.recipient_id = ur.user_id join
users us
on m.sender_id = us.user_id
where m.date = (select max(m2.dat)
from messages m2
where 1 in (m2.recipient_id, m2.sender_id)
) and
1 in (m.recipient_id, m.sender_id);
Here是SQL小提琴。
如果对的排序是导入的(因此select m.*, ur.username as recipient_name, us.username as sender_name
from messages m left join
users ur
on m.recipient_id = ur.user_id left join
users us
on m.owner_id = us.user_id
where m.dat = (select max(m2.dat)
from messages m2
where (m2.recipient_id, m2.owner_id) = (m.recipient_id, m.owner_id) or
(m2.recipient_id, m2.owner_id) = (m.owner_id, m.recipient_id)
) and
1 in (m.recipient_id, m.owner_id);
与(1, 2)
不同,请删除最里面的(2, 1)
子句中的第二个条件。
答案 4 :(得分:0)
您需要使用users表加入最终结果,并根据user_id获取users.username的值。试试这个:
SELECT messages.message_id,
messages.msg,
users.user_id,
users.username
FROM users, messages
JOIN (SELECT user_id,
Max(dat) m
FROM ((SELECT message_id,
users.username,
recipient_id user_id,
dat
FROM messages
INNER JOIN users ON messages.recipient_id = users.user_id
WHERE owner_id = 1)
UNION
(SELECT message_id,
users.username,
owner_id user_id,
dat
FROM messages
INNER JOIN users ON messages.owner_id = users.user_id
WHERE recipient_id = 1)) t1
GROUP BY user_id) t2
ON ( ( owner_id = 1
AND recipient_id = user_id )
OR ( owner_id = user_id
AND recipient_id = 1 ) )
AND ( dat = m )
WHERE users.user_id = messages.user_id
ORDER BY dat DESC