查询消息表中的对话

时间:2017-04-11 08:57:01

标签: mysql sql

我的消息表格式如下:

btack.cpp

我想要做的就是获得所有"对话"已登录用户(例如ID为2的用户)以及该对话的最后消息。 我设法提取用户id2的用户使用此查询的消息:

+------------------------------------------------------------------+
| id|sender_id| recipient_id | message_text |created_at            |
+------------------------------------------------------------------+
| 1 | 2       |  10          | "test1"      |"2017-04-10 09:05:45" |
| 2 | 10      |  2           | "test2"      |"2017-04-10 09:05:47" |
| 3 | 2       |  4           | "test3"      |"2017-04-10 09:05:49" |
| 4 | 10      |  4           | "test4"      |"2017-04-10 09:05:51" |
| 5 | 4       |  2           | "test5"      |"2017-04-10 09:05:53" |
| 6 | 2       |  10          | "test6"      |"2017-04-10 09:05:58" |
+------------------------------------------------------------------+

这会产生什么

select distinct users.id 
from messages, users where 
(recipient_id = 2 and users.id = sender_id) 
or 
(sender_id = 2 and users.id = recipient_id);

因为user2已发送和/或接收来自这两个人的消息(4 10 test1, test2, test610test3, test5

我无法做的是修改此查询,以便它还会生成发送到已生成ID的最后一条消息 - 例如

4

2 个答案:

答案 0 :(得分:3)

如果我正确理解您的要求,您希望获取涉及特定用户的每个对话的最新消息日期。在这种情况下,我们可以聚合给定用户的会话并保留最近的消息日期。

SELECT m1.*
FROM messages m1
INNER JOIN
(
    SELECT LEAST(sender_id, recipient_id)    AS first,
           GREATEST(sender_id, recipient_id) AS second,
           MAX(created_at) AS recent_date
    FROM messages
    WHERE sender_id = 2 OR recipient_id = 2
    GROUP BY LEAST(sender_id, recipient_id),
             GREATEST(sender_id, recipient_id)
) m2
    ON LEAST(m1.sender_id, m1.recipient_id)    = m2.first AND
       GREATEST(m1.sender_id, m1.recipient_id) = m2.second AND
       m1.created_at = m2.recent_date

<强>输出:

enter image description here

<强>解释

此查询中的挑战是找到一种方法将两个用户之间的对话分组在一起。我使用LEAST/GREATEST技巧,这是一种我们可以将2 -> 44 -> 2对话视为逻辑相同的方式。然后,使用GROUP BY,我们可以确定该对转化用户的最近通话日期。因此,上面我的答案中的子查询发现,对于每对用户,不考虑任何顺序,该对以及最近的对话日期。然后,我们将此结果返回到messages表,以引入实际的最新消息文本。

在这里演示:

Rextester

答案 1 :(得分:0)

在查询结尾处使用order_by created_at desc语句来获取最新消息。