你如何编写一个 mysql 查询 returns 最新的相应记录?

How do you write a mysql query that returns the latest respective records?

使用 table(消息)数据结构:

+------+--------+--------+----------+------+--------+
|  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,结果相同。

如果你想要整个记录,你需要过滤,而不是聚合

如果你是运行MySQL8.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) 上的索引,相关子查询可能是一个有效的解决方案。

反过来想更容易:您需要每个 FromId 具有最高索引的记录

SELECT * FROM 'Messages' WHERE id IN (
   SELECT MAX(index) 
   FROM 'Messages' 
   WHERE ToId = 100 
   GROUP BY FromId
)

然后你可以随意排序