SQL两表关联如何取TableB各account对应MAX(date)行
查询场景说明
现有两张数据库表结构如下:
- TableA:包含字段
account、b、c - TableB:包含字段
account、date
需要通过TableA.account = TableB.account条件完成两表关联,关联时仅匹配TableB中每个account分组下date字段取最大值(MAX(date))的对应行,以下是可直接落地的实现方案。
实现方案
方案1:预聚合后关联(全SQL数据库兼容)
这是兼容性最好的写法,支持所有关系型数据库,逻辑为先聚合计算每个account对应的最大date,再关联回原表拿到完整行数据,最后和TableA关联:
SELECT a.account, a.b, a.c, b.date FROM TableA a INNER JOIN ( SELECT account, MAX(date) AS max_date FROM TableB GROUP BY account ) b_group ON a.account = b_group.account INNER JOIN TableB b ON b.account = b_group.account AND b.date = b_group.max_date;
注意:如果同一个account下存在多条date值等于最大值的记录,该写法会返回所有匹配行;如果业务要求每个account仅返回1条记录,可根据业务规则增加去重逻辑,或使用下面的窗口函数方案。
方案2:窗口函数实现(支持现代SQL数据库)
如果使用的数据库支持窗口函数(MySQL 8.0+、PostgreSQL、SQL Server、Oracle 11g+等),可以用ROW_NUMBER()直接分组排序取Top1,写法更简洁,性能也更稳定:
SELECT a.account, a.b, a.c, b.date FROM TableA a INNER JOIN ( SELECT account, date, ROW_NUMBER() OVER (PARTITION BY account ORDER BY date DESC) AS rn FROM TableB ) b ON a.account = b.account WHERE b.rn = 1;
注意:
ROW_NUMBER()遇到同account下多条date相同的最大值记录时,会随机返回其中1条;如果需要返回所有最大date的匹配行,可将ROW_NUMBER()替换为RANK()。
方案3:相关子查询实现(小数据量场景适用)
写法最直观,不需要嵌套多层关联,但数据量较大时子查询会逐行匹配,性能弱于前两种方案,适合数据规模小的场景使用:
SELECT a.account, a.b, a.c, b.date FROM TableA a INNER JOIN TableB b ON a.account = b.account WHERE b.date = ( SELECT MAX(date) FROM TableB b_sub WHERE b_sub.account = a.account );
性能优化建议
建议为TableB的account、date字段创建联合索引,可大幅提升聚合、关联阶段的查询效率。
内容的提问来源于stack exchange,提问作者mrbochin23
相关产品推荐
相关产品推荐

