SQL中不使用DISTINCT如何避免两表关联产生重复行?
解决JOIN多表时的重复行问题
我搞不懂当第二张表有额外细节层级时的JOIN逻辑,现在有两张表table1和table2(示例表如图)。我想把table2里的DOB和table1的数据一起返回,写了下面的查询:
select t1.PERSON ID, t1.Celeb First Name, t1.Celeb Last Name, t2.DOB from table 1 as t1 left join table 2 t2 on t1.personid = t2.personid
哪怕用了GROUP BY,还是会得到重复行。不想用DISTINCT,因为会大幅拖慢查询速度,怎么才能只返回单行数据?
我试过的GROUP BY查询:
select t1.PERSON ID, t1.Celeb First Name, t1.Celeb Last Name, t2.DOB from table 1 as t1 left join table 2 t2 on t1.personid = t2.personid group by t1.PERSON ID, t1.Celeb First Name, t1.Celeb Last Name, t2.DOB
问题原因
你遇到的重复行,本质是table2中同一个personid对应了多条记录,LEFT JOIN会把每条匹配的记录都和table1的行关联,最终输出多行。而你之前的GROUP BY包含了t2.DOB,如果同一个personid下有多条DOB相同的记录,或者存在不同DOB的情况,GROUP BY无法合并成单行。
可行解决方案
1. 用聚合函数提取唯一DOB(推荐)
正常来说,同一个人的出生日期(DOB)是唯一的,所以可以用MAX()或MIN()这类聚合函数对t2.DOB取值,同时GROUP BY只包含table1的字段,确保每个personid只返回一行:
select t1.PERSON ID, t1.Celeb First Name, t1.Celeb Last Name, MAX(t2.DOB) as DOB from table 1 as t1 left join table 2 t2 on t1.personid = t2.personid group by t1.PERSON ID, t1.Celeb First Name, t1.Celeb Last Name
2. 先对table2去重再关联
如果table2里同一个personid有重复的DOB记录,可以先对table2做去重处理,再和table1 JOIN:
select t1.PERSON ID, t1.Celeb First Name, t1.Celeb Last Name, t2.DOB from table 1 as t1 left join (select distinct personid, DOB from table 2) t2 on t1.personid = t2.personid
3. 用窗口函数筛选唯一行
如果需要灵活选择某一条记录的DOB(比如取最新录入的),可以用ROW_NUMBER()窗口函数给table2的记录按personid分组排序,只保留每组的第一行:
select t1.PERSON ID, t1.Celeb First Name, t1.Celeb Last Name, t2.DOB from table 1 as t1 left join (select personid, DOB, ROW_NUMBER() over (partition by personid order by 录入时间 desc) as rn from table 2) t2 on t1.personid = t2.personid and t2.rn = 1
注:上面的录入时间需要替换成table2中实际的排序字段,如果没有特定排序逻辑,用order by (select null)也可以随机取一行。
内容的提问来源于stack exchange,提问作者jrj
相关产品推荐
相关产品推荐

