GROUP BY与ORDER BY在UNION场景下的问题:如何获取分组最新数据
解决每组取最新记录的SQL问题
嘿,这个问题其实是SQL里非常常见的「每组取最新一条记录」的场景,你之前用GROUP BY的思路其实走偏了——GROUP BY是用来做聚合统计的,不是用来筛选每组内的特定行的,所以哪怕后面加ORDER BY也没法达到你要的效果。我给你两种靠谱的解决方案,看你用的数据库版本选就行:
方法1:用窗口函数ROW_NUMBER()(推荐,适用于MySQL 8+、PostgreSQL、SQL Server等现代数据库)
这是最简洁高效的写法,利用窗口函数给每个分组内的记录排序,然后取每组的第一条:
WITH ranked_records AS ( SELECT *, -- 按description和price分组,每组内按创建时间倒序排,最新的排第1 ROW_NUMBER() OVER (PARTITION BY description, price ORDER BY created_at DESC) AS row_rank FROM your_table -- 如果有你提到的UNION查询,直接把UNION结果当数据源就行: -- FROM (SELECT * FROM table_a UNION SELECT * FROM table_b) AS combined_data ) -- 只取每组排名第1的记录(也就是最新的那条) SELECT * FROM ranked_records WHERE row_rank = 1;
解释:
PARTITION BY description, price:把数据按你要的两个字段分成一个个独立的组ORDER BY created_at DESC:让每个组内的记录按时间从新到旧排序,最新的会被标记为row_rank=1- 最后筛选
row_rank=1就拿到了每个分组的最新记录
如果你的「最新」不是按时间判断,而是按自增ID(比如id),只要把ORDER BY created_at DESC换成ORDER BY id DESC就行,逻辑完全一致。
方法2:子查询关联(适用于不支持窗口函数的旧版数据库,比如MySQL 5.x)
如果你的数据库版本比较旧,不支持窗口函数,可以用关联子查询来实现:
SELECT t.* FROM your_table t WHERE t.created_at = ( -- 找到当前分组(description+price)里的最大时间,也就是最新记录的时间 SELECT MAX(t2.created_at) FROM your_table t2 WHERE t2.description = t.description AND t2.price = t.price );
注意:如果同一个分组里有多条记录在同一时间创建(也就是多个「最新」),这个写法会返回所有符合的记录。如果你只要其中一条,可以在子查询里加LIMIT 1(MySQL)或者TOP 1(SQL Server)来限制。
另外你提到的UNION其实完全不影响,不管是哪种方法,只要把UNION的查询结果当作数据源替换掉your_table就可以了,比如把FROM your_table换成FROM (SELECT ... UNION SELECT ...) AS combined。
内容的提问来源于stack exchange,提问作者Tompina
相关产品推荐
相关产品推荐

