如何编写SQL查询:按Report_number分组,无编号则保留全记录
优化SQL查询方案:分组有编号报告+全列无编号报告
方案1:用窗口函数(首推,性能更好)
用ROW_NUMBER()窗口函数就能一次搞定,不用拆成两个查询再UNION,效率更高。核心思路是:给每个有编号的报告组编行号,只留每组第一行;无编号的报告单独成组,自然全部保留。
举个实际例子(假设表名叫reports,字段有id, content, report_number, create_time,要取每组最新的报告):
SELECT id, content, report_number, create_time FROM ( SELECT id, content, report_number, create_time, -- 有编号的按编号分组,无编号的按自己id分组(保证每条都是单独一组) -- 每组按创建时间倒序,行号1就是最新的那条 ROW_NUMBER() OVER ( PARTITION BY CASE WHEN report_number IS NOT NULL THEN report_number ELSE id END ORDER BY create_time DESC ) AS rn FROM reports ) t WHERE rn = 1;
要是你不想取最新的,把ORDER BY create_time DESC改成ASC就能取最早的,或者按其他字段排序都行。
方案2:聚合函数+UNION ALL(兼容老版本数据库)
如果你的数据库不支持窗口函数(比如老版MySQL),可以用这个备选方案。注意用UNION ALL代替UNION,因为不用做去重,速度更快:
-- 先取有编号的每组一条(这里拿id最大的记录当代表) SELECT MAX(id) AS id, MAX(content) AS content, report_number, MAX(create_time) AS create_time FROM reports WHERE report_number IS NOT NULL GROUP BY report_number UNION ALL -- 再取所有无编号的记录 SELECT id, content, report_number, create_time FROM reports WHERE report_number IS NULL;
聚合函数选MAX还是MIN,根据你要保留哪条记录来定。
为啥比原来的UNION好?
- 窗口函数方案只需要扫一次表,大数据量下性能碾压两次扫描的UNION方案
- 就算用UNION ALL的备选,也比原来的UNION快,因为少了去重的开销
内容的提问来源于stack exchange,提问作者qed59
相关产品推荐
相关产品推荐

