如何查询列表中每个条目对应最大日期的行数据?
高效获取每个分组的最大日期行数据
你现在用UNION ALL逐个查询每个String的最大日期行,虽然能正常工作,但确实不够高效——尤其是当数据量变大或者String种类增多时,重复的子查询会带来不必要的性能开销。下面给你几种更简洁高效的实现方式:
方法1:使用窗口函数(推荐,现代SQL数据库都支持)
窗口函数是处理这类分组Top N问题的最优解之一,只需要扫描一次表就能完成计算:
WITH ranked_dates AS ( SELECT String, Dates, ROW_NUMBER() OVER (PARTITION BY String ORDER BY Dates DESC) AS rn FROM your_table_name ) SELECT String, Dates FROM ranked_dates WHERE rn = 1;
- 原理:
PARTITION BY String按每个String分组,ORDER BY Dates DESC把每个组里的日期从大到小排序,ROW_NUMBER()给每个组的行标序号,最大日期的行序号就是1,最后筛选出rn=1的行即可。 - 优势:只需要一次全表扫描,性能远优于多次
UNION ALL的方式,而且扩展性强——不管新增多少个String,都不需要修改SQL。
方法2:分组子查询关联
如果你的数据库不支持窗口函数(比如一些老版本的MySQL),可以用分组子查询先获取每个String的最大日期,再和原表关联:
SELECT t.String, t.Dates FROM your_table_name t INNER JOIN ( SELECT String, MAX(Dates) AS max_date FROM your_table_name GROUP BY String ) m ON t.String = m.String AND t.Dates = m.max_date;
- 原理:先通过子查询分组计算每个String的最大日期,再通过
INNER JOIN匹配原表中对应String和最大日期的行。 - 优势:比
UNION ALL简洁,而且同样只需要两次表扫描(一次分组,一次关联),性能比多次子查询好很多。
为什么你的原方法不够高效?
原来的UNION ALL方式,每个String都要执行一次主查询+子查询,相当于对表执行了10次扫描(5次主查询+5次子查询),当数据量增大时,性能会线性下降。而上面两种方法最多只需要2次扫描,效率提升非常明显。
内容的提问来源于stack exchange,提问作者Bryan C.H Li
相关产品推荐
相关产品推荐

