简体   繁体   English

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

[英]MySQL query to group messages into a conversation and show the first in the inbox

Say for example two users talk via direct message, you will have a conversation of messages .. I want to just select the latest message from that conversation and then show it as the conversation link in their message inbox ... just how Facebook and Twitter messages work.例如,两个用户通过直接消息交谈,您将进行消息对话......我只想从该对话中选择最新消息,然后将其显示为他们消息收件箱中的对话链接......就像 Facebook 和 Twitter消息工作。 They can then click that last sent message to view the whole conversation.然后,他们可以单击最后发送的消息以查看整个对话。

My messages table that contains all messages sent between users is in the following format:我的消息表包含用户之间发送的所有消息,格式如下:

sourceUserId is the id of the user who sent the message, targetUserId is the id of the user who received the message, body is the message, time is a timestamp of when the message was sent. sourceUserId 是发送消息的用户的id,targetUserId 是接收消息的用户的id,body 是消息,time 是消息发送的时间戳。 I have kept body as abc... and time 1234 to keep this example simple, they are all different values.我将 body 保持为 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 |
+----+--------------+--------------+--------+------+

To get all the messages (sent and received) for one user, I use this query:要获取一个用户的所有消息(发送和接收),我使用以下查询:

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 |
+----+--------------+--------------+--------+------+

but it returns multiple instances of the same message conversation and not just the latest message from a conversation between two users.它返回同一消息对话的多个实例,而不仅仅是来自两个用户之间对话的最新消息。 Take for example rows 2,3 and 4 would all show exactly the same conversation.例如,第 2,3 和 4 行将显示完全相同的对话。

I can get the query to work for just targetUserId (messages the user has received) with the following query:我可以使用以下查询使查询仅适用于 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 |
+----+--------------+--------------+--------+------+

and the opposite (messages sent by the user) with this, note that WHERE and GROUP BY have just been swapped:与此相反(用户发送的消息),请注意 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 |
+----+--------------+--------------+--------+------+

but if I combine the two results and group by targetUserId, sourceUserId then it does not give the correct result because all outgoing messages from 1 to (2,3,4) are grouped.但是如果我将两个结果组合起来并按group by targetUserId, sourceUserId那么它不会给出正确的结果,因为从 1 到 (2,3,4) 的所有传出消息都被分组。

What I would like to return我想返回什么

I think the Pseudo Code for such a query would be:我认为这种查询的伪代码是:

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 |
+----+--------------+--------------+--------+------+

VERSION 2 This is untested;版本 2 这是未经测试的; it is closer but still not right... out of time though on working on this...它更接近但仍然不正确......虽然在这方面工作已经过时了......

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

VERSION 1 (Miss) IMO you need to group by body as well. VERSION 1 (Miss) 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

Or use distinct或者使用不同的

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

I think the problem is really in that body is different or timestamp is different for those records;我认为问题真的在于那些记录的主体不同或时间戳不同; if not, then why are they duplicated in the table?如果没有,那么为什么它们在表中重复? Specifically in your output why are records 1 & 6 there... are you missing a unique index/pk which would prevent duplicates?特别是在您的输出中,为什么记录 1 和 6 存在……您是否缺少一个可以防止重复的唯一索引/pk?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM