MySQL查询将消息分组到对话中并在收件箱中显示第一个消息

时间:2012-05-09 16:28:19

标签: mysql database

例如,假设两个用户通过直接消息进行通话,您将进行消息对话..我只想从该对话中选择最新消息,然后将其显示为消息收件箱中的对话链接... Facebook和Twitter消息有效。然后,他们可以点击最后发送的消息来查看整个会话。

我的消息表包含用户之间发送的所有消息,格式如下:

sourceUserId是发送邮件的用户的id,targetUserId是收到邮件的用户的id,body是邮件,time是邮件发送时的时间戳。我保持身体为abc ...和时间1234以保持这个例子简单,它们都是不同的值。

+----+--------------+--------------+--------+------+
| id | sourceUserId | targetUserId |  body  | time |
+----+--------------+--------------+--------+------+
| 1  |       1      |       2      | abc... | 1234 |
| 2  |       3      |       1      | abc... | 1234 |
| 3  |       3      |       1      | abc... | 1234 |
| 4  |       1      |       3      | abc... | 1234 |
| 5  |       2      |       1      | abc... | 1234 |
| 6  |       1      |       2      | abc... | 1234 |
| 7  |       3      |       1      | abc... | 1234 |
| 8  |       4      |       1      | abc... | 1234 |
| 9  |       5      |       4      | abc... | 1234 |
| 10 |       3      |       2      | abc... | 1234 |
+----+--------------+--------------+--------+------+

要获取一个用户的所有消息(已发送和已接收),我使用此查询:

SELECT sourceUserId, targetUserId, body,  UNIX_TIMESTAMP(time)  
FROM `usermessages`
WHERE targetUserId = 1
OR sourceUserId = 1
ORDER BY id DESC
LIMIT 10

+----+--------------+--------------+--------+------+
| id | sourceUserId | targetUserId |  body  | time |
+----+--------------+--------------+--------+------+
| 1  |       1      |       2      | abc... | 1234 |
| 2  |       3      |       1      | abc... | 1234 |
| 3  |       3      |       1      | abc... | 1234 |
| 4  |       1      |       3      | abc... | 1234 |
| 5  |       2      |       1      | abc... | 1234 |
| 6  |       1      |       2      | abc... | 1234 |
| 7  |       3      |       1      | abc... | 1234 |
| 8  |       4      |       1      | abc... | 1234 |
+----+--------------+--------------+--------+------+

它会返回同一消息对话的多个实例,而不仅仅是两个用户之间对话的最新消息。例如,第2,3和4行都会显示完全相同的对话。

我可以使用以下查询让查询仅用于targetUserId(用户收到的消息):

SELECT sourceUserId, targetUserId, body,  UNIX_TIMESTAMP(time)  
FROM `usermessages`
WHERE targetUserId = 1
GROUP BY sourceUserId
ORDER BY id DESC
LIMIT 10

+----+--------------+--------------+--------+------+
| id | sourceUserId | targetUserId |  body  | time |
+----+--------------+--------------+--------+------+
| 2  |       3      |       1      | abc... | 1234 |
| 5  |       2      |       1      | abc... | 1234 |
| 8  |       4      |       1      | abc... | 1234 |
+----+--------------+--------------+--------+------+

和相反的(用户发送的消息),注意刚刚交换了WHERE和GROUP BY:

SELECT sourceUserId, targetUserId, body,  UNIX_TIMESTAMP(time)  
FROM `usermessages`
WHERE sourceUserId = 1
GROUP BY targetUserId
ORDER BY id DESC
LIMIT 10

+----+--------------+--------------+--------+------+
| id | sourceUserId | targetUserId |  body  | time |
+----+--------------+--------------+--------+------+
| 1  |       1      |       2      | abc... | 1234 |
| 4  |       1      |       3      | abc... | 1234 |
+----+--------------+--------------+--------+------+

但是如果我将两个结果和group by targetUserId, sourceUserId结合起来,则它不会给出正确的结果,因为从1到(2,3,4)的所有传出消息都被分组。

我想返回的内容

我认为这种查询的伪代码是:

SELECT sourceUserId, targetUserId, body,  UNIX_TIMESTAMP(time)  
FROM `usermessages`
WHERE sourceUserId = 1
OR targetUserId = 1
GROUP BY (If targetUserId != 1), (If sourceUserId != 1)
ORDER BY id DESC
LIMIT 10

+----+--------------+--------------+--------+------+
| id | sourceUserId | targetUserId |  body  | time |
+----+--------------+--------------+--------+------+
| 1  |       1      |       2      | abc... | 1234 |
| 2  |       3      |       1      | abc... | 1234 |
| 8  |       4      |       1      | abc... | 1234 |
+----+--------------+--------------+--------+------+

1 个答案:

答案 0 :(得分:2)

版本2 这是未经测试的;它离得更近了,但仍然不对......时间虽然在研究这个......

SELECT Um1.sourceUserId, Um1.targetUserId, um1.body,  UNIX_TIMESTAMP(um1.time)  
FROM usermessages um1
WHERE um1.time = 
   (Select max(um1.time) 
    FROM usermessages um2 
    where um1.sourceUserID = um2.sourceUserID 
      and Um1.targetUserID = Um2.targetUserID, 
      and UM1.Body = UM2.body 
      and (targetuserID = 1 or sourceuserID = 1))
Group by Um1.sourceUserId, Um1.targetUserId, um1.body
ORDER BY id DESC
LIMIT 10

版本1(小姐) IMO你也需要按身体分组。

SELECT sourceUserId, targetUserId, body,  UNIX_TIMESTAMP(time)  
FROM `usermessages`
WHERE targetUserId = 1
OR sourceUserId = 1
GROUP BY sourceUserId, targetUserId, body,  UNIX_TIMESTAMP(time)
ORDER BY id DESC
LIMIT 10

或使用不同的

SELECT distinct sourceUserId, targetUserId, body,  UNIX_TIMESTAMP(time)  
FROM `usermessages`
WHERE targetUserId = 1
OR sourceUserId = 1
ORDER BY id DESC
LIMIT 10

我认为问题实际上是因为这些记录的身体不同或时间戳不同;如果没有,那么为什么它们会在表格中重复出现?特别是在你的输出中为什么记录1& 6那里......你错过了一个可以防止重复的唯一索引/ pk吗?