请求提供合适SQL查询:获取每个对话的最新短信记录
嘿,这个需求挺常见的,我来帮你搞定!要找出每个对话里的最新短信,核心思路就是先按对话分组,然后每组里挑出时间最晚的那条记录。下面给你几种不同的实现方案,你可以根据自己用的数据库版本来选:
方案1:使用窗口函数(推荐,适用于支持窗口函数的数据库:MySQL 8.0+、PostgreSQL、SQL Server等)
窗口函数ROW_NUMBER()可以给每个对话组内的记录按时间排序,然后取排序为1的那条(也就是最新的)。假设你的sms表结构大概包含这些字段:
id:短信唯一IDsender:发送方号码receiver:接收方号码content:短信内容send_time:发送时间(用来判断最新的核心字段)
注意:对话的标识需要特殊处理——比如A发给B和B发给A应该算同一个对话,所以分组时要用LEAST()和GREATEST()函数统一对话的标识,避免把双向消息拆成两个不同对话。
查询语句如下:
WITH ranked_sms AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY LEAST(sender, receiver), GREATEST(sender, receiver) ORDER BY send_time DESC ) AS rn FROM sms ) SELECT id, sender, receiver, content, send_time FROM ranked_sms WHERE rn = 1;
简单解释下:
PARTITION BY LEAST(sender, receiver), GREATEST(sender, receiver):把发送方和接收方按固定大小顺序组合,确保双向消息被分到同一个对话组ORDER BY send_time DESC:每个组内按发送时间倒序排列,最新的短信排在最前面rn = 1:筛选出每个组的第一条记录,也就是该对话的最新短信
如果你的表本身有专门的conversation_id字段(用来唯一标识对话),那分组会更简单,直接把PARTITION BY后的字段换成conversation_id即可。
方案2:子查询+关联查询(适用于不支持窗口函数的老版本MySQL,比如5.7及以下)
如果你的数据库不支持窗口函数,可以用这种传统方法:先找出每个对话的最新发送时间,再关联原表匹配对应的记录。
SELECT s.* FROM sms s INNER JOIN ( SELECT LEAST(sender, receiver) AS party1, GREATEST(sender, receiver) AS party2, MAX(send_time) AS latest_time FROM sms GROUP BY party1, party2 ) latest ON LEAST(s.sender, s.receiver) = latest.party1 AND GREATEST(s.sender, s.receiver) = latest.party2 AND s.send_time = latest.latest_time;
解释:
- 子查询先按对话分组,计算出每个对话的最新发送时间
- 把原表和子查询关联,通过对话标识+最新时间匹配,得到对应的短信记录
⚠️ 小提醒:如果同一个对话在同一时间有多条短信(send_time完全相同),这个方案会返回多条记录。如果要确保每个对话只返回一条,可以在子查询里加上MAX(id)(或其他唯一标识字段),关联时再加上该字段的匹配条件。
补充说明
请根据你的实际表结构调整字段名,比如如果时间字段叫create_time而非send_time,记得替换;如果对话的定义和我假设的不同(比如按特定会话ID分组),直接修改PARTITION BY或GROUP BY后的字段即可。
内容的提问来源于stack exchange,提问作者nuamehas
相关产品推荐
相关产品推荐

