如何获取每个分组的最新2条记录?无需为每个分组单独查询
嘿,这个需求太常见啦,完全不用给每种颜色单独写查询!用窗口函数就能优雅解决这问题,这也是处理分组取Top N记录的标准方案。下面针对不同主流数据库给你具体实现方式:
分组取每种颜色最新2条记录的实现方案
核心思路是通过窗口函数给每个颜色组内的记录按“新旧程度”编号,再筛选出编号≤2的记录;如果是老版本数据库不支持窗口函数,也有替代方案。
1. 通用标准SQL写法(支持窗口函数的数据库:MySQL 8.0+、PostgreSQL、SQL Server 2012+等)
假设你的表名为color_data,包含color(颜色字段)、update_time(判断新旧的时间字段),还有其他业务字段比如id、detail:
SELECT id, color, update_time, detail FROM ( SELECT *, -- 按颜色分组,组内按时间倒序编号,最新的排第1 ROW_NUMBER() OVER (PARTITION BY color ORDER BY update_time DESC) AS row_num FROM color_data ) temp WHERE row_num <= 2;
- 小细节:
- 如果你的场景中,同颜色下有多条记录时间完全相同,且希望这些记录都被算作“最新”(比如时间相同的都保留),可以把
ROW_NUMBER()换成RANK()或者DENSE_RANK(),这两个函数会给相同时间的记录分配相同编号 - 要是判断“最新”的依据是自增ID(ID越大越新),把
ORDER BY update_time DESC改成ORDER BY id DESC就行
- 如果你的场景中,同颜色下有多条记录时间完全相同,且希望这些记录都被算作“最新”(比如时间相同的都保留),可以把
2. MySQL 5.x等不支持窗口函数的老版本
如果用的是比较老的数据库,没法用窗口函数,可以用关联子查询的方式实现:
SELECT c1.* FROM color_data c1 WHERE ( -- 统计同颜色下,时间大于等于当前记录的条数 SELECT COUNT(*) FROM color_data c2 WHERE c2.color = c1.color AND c2.update_time >= c1.update_time ) <= 2 ORDER BY c1.color, c1.update_time DESC;
- 优化提示:记得给
color和update_time建立联合索引,不然数据量大的时候查询会很慢哦!
内容的提问来源于stack exchange,提问作者lost111in
相关产品推荐
相关产品推荐

