使用表(消息)的数据结构:
+------+--------+--------+----------+------+--------+
| id | FromId | ToId | sentdate | text | index |
+------+--------+--------+----------+------+--------+
| guid | 200 | 100 | 3/9/20 | 2c | 6 |
| guid | 400 | 100 | 3/8/20 | 4a | 5 |
| guid | 100 | 200 | 3/8/20 | 2b | 4 |
| guid | 300 | 100 | 3/7/20 | 3a | 3 |
| guid | 200 | 100 | 3/6/20 | 2a | 2 |
| guid | 300 | 200 | 3/5/20 | 1a | 1 |
+------+--------+--------+----------+------+--------+
SELECT *
FROM `Messages`
WHERE FromId IN (
SELECT DISTINCT FromId
FROM `Messages`
WHERE ToId = '100')
GROUP BY FromId ORDER BY index DESC
预期结果应该是(每个发件人的最新记录:
+------+--------+--------+----------+------+--------+
| id | fromid | toid | sentdate | text | index |
+------+--------+--------+----------+------+--------+
| guid | 200 | 100 | 3/9/20 | 2c | 6 |
| guid | 400 | 100 | 3/8/20 | 4a | 5 |
| guid | 300 | 100 | 3/7/20 | 3a | 3 |
+------+--------+--------+----------+------+--------+
但是,在执行GROUP BY之后,会出现以下结果(排序不正确):
+------+--------+--------+----------+------+--------+
| id | fromid | toid | sentdate | text | index |
+------+--------+--------+----------+------+--------+
| guid | 400 | 100 | 3/8/20 | 4a | 5 |
| guid | 300 | 100 | 3/7/20 | 3a | 3 |
| guid | 200 | 100 | 3/6/20 | 2a | 2 |
+------+--------+--------+----------+------+--------+
您如何优化每个发件人的最新记录,而又不返回所有记录?我在子查询中尝试了JOIN和ORDER BY,结果相同。
如果要整个记录,则需要过滤,而不是聚合。
如果您正在运行MySQL 8.0,则可以使用row_number()
:
select *
from (
select m.*, row_number() over(partition by fromid order by sentdate desc) rn
from messages m
) t
where rn = 1
您还可以使用相关子查询进行过滤(这将在旧版本的MySQL上运行:]
select m.*
from messages m
where m.sentdate = (
select max(m1.sentdate) from messages m1 where m1.fromid = m.fromid
)
使用在(fromid, sentdate)
上的索引,相关子查询可能是一个有效的解决方案。
您将加入一个合计:
SELECT m1.*
FROM messages AS m1
JOIN (
SELECT FromId, MAX(sentdate) AS max_sentdate
FROM messages AS x
WHERE x.ToId = m1.ToId
GROUP BY FromId
) AS m2 ON m1.FromId = m2.FromId AND m1.sentdate = m2.sentdate
WHERE m1.ToId = 100
更容易反过来考虑:您需要每个FromId具有最高ID的记录
SELECT * FROM 'Messages' WHERE id IN (
SELECT MAX(id)
FROM 'Messages'
WHERE ToId = 100
GROUP BY FromId
)
然后您可以根据需要对其进行排序