1:多表关联SQL查询:如何筛选关联表最新记录并实现1:1结果集
兄弟,你的SQL思路踩了执行顺序的坑啦
首先得给你掰扯清楚SQL的执行逻辑:GROUP BY是在ORDER BY之前运行的,完整的执行流程大概是这样:
- 先执行
FROM和JOIN,把Table1和Table2的关联行全拉出来 - 接着执行
GROUP BY t1.Id,这时候数据库会把同一个t1.Id的行归成一组,但对于t2.value和t2.Date这种没在GROUP BY里的字段,数据库只会随机挑组里的某一行(不同数据库规则可能有点差异,但绝对不会因为后面的ORDER BY就选最新的那条) - 最后才轮到
ORDER BY t2.Date DESC,这只是给分组后的结果排个序,根本改变不了分组时选的是哪条t2记录
所以你的这条语句大概率拿不到每个主表对应的最新子表记录,反而可能拿到随机的一条,完全达不到你的需求。
正确的实现姿势(不用UNION哦)
最常用也最靠谱的方法是用窗口函数ROW_NUMBER(),它能帮我们给每个Id对应的Table2行按Date降序编个号,然后只取编号为1的那一行(也就是最新的那条):
WITH RankedTable2 AS ( SELECT Id, Value, Date, -- 按Id分组,每组内按Date倒序编号 ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Date DESC) AS rn FROM Table2 ) SELECT t1.Id, t1.Name, rt2.Value, rt2.Date FROM Table1 t1 INNER JOIN RankedTable2 rt2 ON t1.Id = rt2.Id WHERE rt2.rn = 1;
如果你用的数据库不支持CTE(比如老版本的MySQL),也可以用关联子查询的方式,先找到每个Id对应的最大Date,再关联回Table2:
SELECT t1.Id, t1.Name, t2.Value, t2.Date FROM Table1 t1 INNER JOIN Table2 t2 ON t1.Id = t2.Id INNER JOIN ( SELECT Id, MAX(Date) AS MaxDate FROM Table2 GROUP BY Id ) latest ON t2.Id = latest.Id AND t2.Date = latest.MaxDate;
这两种方法都比用UNION简洁高效,而且能精准拿到每个主表记录对应的最新子表行,完全满足你的1:1结果集需求。
内容的提问来源于stack exchange,提问作者fr332lanc3
相关产品推荐
相关产品推荐

