首页 > 解决方案 > 从所有对话中选择最后一条消息(MySQL)

问题描述

我需要为具有给定 ID 的用户选择每个对话的所有最后消息。
如果最后一条消息被发送到给定的 id,它必须是来自发件人的最后一条消息。

这是没有使用 messageID 的 creationDate 的测试用例:

+-----------+------------+----------+------+
| messageID | fromUserID | toUserID | text |
+-----------+------------+----------+------+
| 1         | 1          | 2        | 'aa' |
| 2         | 1          | 3        | 'ab' |
| 3         | 2          | 1        | 'ac' |
| 4         | 2          | 1        | 'ad' |
| 5         | 3          | 2        | 'ae' |
+-----------+------------+----------+------+

userID=1 的结果必须是带有文本“ab”和“ad”的消息。

现在,我有这个查询,其中包含每个用户彼此的所有最后消息,但根据我的测试用例,没有删除 id=1 的消息(必须只有 id=2 和 id=4)。

SELECT
    UM.messageID,
    UM.fromUserID, UM.toUserID,
    UM.text, UM.flags, UM.creationDate
FROM UserMessage AS UM
INNER JOIN
    (
        SELECT
            MAX(messageID) AS maxMessageID
        FROM UserMessage
        GROUP BY fromUserID, toUserID
    ) IUM
    ON UM.messageID = IUM.maxMessageID
WHERE UM.fromUserID = 1 OR UM.toUserID = 1
ORDER BY UM.messageID DESC

在此处输入图像描述

标签: mysqlsqldatabasemessage

解决方案


一个简单的方法是

select um.*
from usermessage um
where um.messageid = (select min(um2.messageid)
                      from usermessage um2
                      where (um2.fromuserid, touserid) in ( (um.fromuserid, um.touserid), (um.touserid, um.fromuserid) )
                     );

或者,在 MySQL 8+ 中:

select um.*
from (select um.*,
             row_number() over (partition by least(um.fromuserid, um.touserid), greatest(um.fromuserid, um.touserid) order by um.messageid desc) as seqnum
      from usermessage um
     ) um
where seqnum = 1;

推荐阅读