如何查询无重复的各发送者最新消息记录?
解决方法:获取各发送者的最新消息(无重复)
方法1:使用窗口函数(推荐,适用于MySQL 8.0+、PostgreSQL等支持窗口函数的数据库)
用ROW_NUMBER()窗口函数给每个发送者的消息按时间排序,标记出最新的那条(行号为1),再筛选出这些记录即可:
SELECT msg_id, message, account_id, name FROM ( SELECT messages.id AS msg_id, messages.message, account.id AS account_id, account.name, ROW_NUMBER() OVER (PARTITION BY account.id ORDER BY messages.date DESC, messages.time DESC) AS rn FROM account INNER JOIN messages ON account.id = messages.sender_id WHERE receiver_id = 89 ) AS temp WHERE rn = 1;
逻辑说明:
PARTITION BY account.id:按发送者ID分组,每组内单独处理消息排序ORDER BY messages.date DESC, messages.time DESC:每组内按消息的日期、时间倒序排列,最新消息排在最前rn = 1:只保留每组中排第一的记录,也就是该发送者的最新消息
方法2:使用子查询匹配最新时间(兼容低版本MySQL)
如果你的数据库不支持窗口函数,可以先通过子查询找到每个发送者的最新消息时间,再关联查询对应消息:
SELECT messages.id, messages.message, account.id, account.name FROM account INNER JOIN messages ON account.id = messages.sender_id WHERE receiver_id = 89 AND (messages.date, messages.time) = ( SELECT MAX(date), MAX(time) FROM messages WHERE sender_id = account.id AND receiver_id = 89 );
逻辑说明:
- 子查询会为每个发送者,找出其给
receiver_id=89发送的最新消息的日期和时间 - 主查询只保留匹配这个最新时间的消息,确保每个发送者仅返回一条最新记录
原有查询问题分析
- 第一个查询:没有去重逻辑,会返回每个发送者的所有消息,因此出现重复的发送者记录
- 第二个查询:
GROUP BY account.id时,非聚合列(如messages.id、messages.message)会被随机取值,并非最新消息,因此丢失了目标记录
内容的提问来源于stack exchange,提问作者Vishal Kumar
相关产品推荐
相关产品推荐

