SQL查询使用distinct后仍返回重复记录的关联查询改写咨询
问题成因
- 核心原因是
Address表和UserAddress表是1对多的关联关系:1个addressID在Address表中只有1条记录,但在UserAddress表中存在2条对应关联条目。 - 你使用
INNER JOIN时,1行地址数据会匹配到2行用户地址关联数据,最终返回2行内容完全一致的结果。 - 你移除
addressID字段后DISTINCT可以去重,是因为剩余的地址属性完全相同,DISTINCT会合并相同行;而保留addressID时依然返回重复,本质是JOIN产生的重复行未被正确过滤,并非addressID本身不唯一。
重写查询方案
你不需要依赖不稳定的rownum,以下几种写法兼容性强,结果可控:
方案1:使用EXISTS子查询(最推荐,性能最优)
直接判断地址是否存在关联的用户地址记录,不会触发JOIN的行放大效应,天然返回唯一地址:
select a.addressID,a.StreetNumber,a.Street,a.StreetType,a.PostalCode from Address a where exists ( select 1 from UserAddress ca where a.addressID = ca.addressID )
方案2:先对关联表去重再JOIN
如果你后续需要用到UserAddress的其他字段,可以先对UserAddress按addressID去重,再做1对1关联:
select a.addressID,a.StreetNumber,a.Street,a.StreetType,a.PostalCode from Address a inner join ( -- 先对关联表的addressID去重,避免1对多关联 select distinct addressID from UserAddress ) ca on a.addressID = ca.addressID
方案3:窗口函数指定取数规则(需要指定关联记录优先级时用)
如果你需要明确取UserAddress中最新/最早的1条关联记录,可以用窗口函数,比rownum结果可控:
select a.addressID,a.StreetNumber,a.Street,a.StreetType,a.PostalCode from Address a inner join ( select addressID, -- 按addressID分组,可自定义排序规则,比如按创建时间倒序取最新 row_number() over(partition by addressID order by create_time desc) as rn from UserAddress ) ca on a.addressID = ca.addressID and ca.rn = 1
内容的提问来源于stack exchange,提问作者Notion
相关产品推荐
相关产品推荐

