我的消息表包含用户之间发送的所有消息,格式如下:
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 |
+----+--------------+--------------+--------+------+
答案 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吗?