簡體   English   中英

MySQL查詢將消息分組到一個對話中並在收件箱中顯示第一個

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

例如,兩個用戶通過直接消息交談,您將進行消息對話......我只想從該對話中選擇最新消息,然后將其顯示為他們消息收件箱中的對話鏈接......就像 Facebook 和 Twitter消息工作。 然后,他們可以單擊最后發送的消息以查看整個對話。

我的消息表包含用戶之間發送的所有消息,格式如下:

sourceUserId 是發送消息的用戶的id,targetUserId 是接收消息的用戶的id,body 是消息,time 是消息發送的時間戳。 我將 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 |
+----+--------------+--------------+--------+------+

要獲取一個用戶的所有消息(發送和接收),我使用以下查詢:

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

版本 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

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

或者使用不同的

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?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM