我有一张包含消息的表格(简化):
MessageId,
FromUserId,
ToUserId,
Text
并希望将查询输出作为这样的聊天列表:
LastMessageId,
UserId,
Text
所以基本上创建一个对FromUserId和ToUserId进行分组的查询,但前提是其中一个是我自己的userId。
所以我想出了这个:
SELECT (MessageId)
,(Text)
,(FromUserId)
,(ToUserId)
FROM [Messages] a
inner join (select FromUserId as FromId, ToUserId as ToId, Max(MessageId) as MaxId from Messages where MessageId > 0 group by FromUserId, ToUserId) as b on
a.MessageId = b.MaxId
join users u on FromUserId = u.userId
where ToUserId = 123 or FromUserId = 123
有了这个,我就在那里输出(比如123是我的用户ID):
MessageId, Text, FromUserId, ToUserId
1 bla 123 345
2 bla2 345 123
3 bla3 678 123
4 bla4 123 678
我想有这样的输出:
MessageId, Text, UserId
2 bla2 345
4 bla4 678
所以我省略了自己的用户ID,并且只有每次会话的最后一条消息。
这可以在1个查询中完成吗?到目前为止,我只是收到所有消息并通过代码处理此消息。
答案 0 :(得分:1)
SELECT * FROM messages WHERE MessageId IN
(
SELECT DISTINCT
CASE WHEN m2.MessageId IS NULL THEN m1.MessageId
WHEN m1.MessageId > m2.MessageId THEN m1.MessageId ELSE m2.MessageId END
FROM messages m1
LEFT JOIN messages m2 ON
(m1.FROMUSERID = m2.ToUserId
AND m2.FROMUSERID = m1.ToUserId
AND m1.MessageId != m2.MessageId)
)
-- AND (messages.FROMUSERID = 123 or messages.ToUserId = 123)
答案 1 :(得分:0)
这是一种方法,首先将消息表组合起来,以获得一列UserId
和其他信息。然后,它使用row_number()
函数查找每个用户的最新消息,并使用segnum = 1
选择该消息:
SELECT MessageId, Text, UserId
FROM (SELECT MessageId, Text, UserId,
row_number() over (partition by UserId order by MessageId desc) as seqnum
FROM ((select FromUserId as UserId, MessageId, Text
Messages m
) union all
(select ToUserId as UserId, MessageId, Text
Messages m
)
) m
) m
WHERE seqnum = 1;
如果要将此限制为一个用户,可以向每个子查询添加where FromUserId = @X or ToUserId = @X
(最好在union all
之前执行此操作。)