Oracle左连接返回记录数超左表,两次连接去重方案咨询
Oracle两次关联去重解决方案
问题分析
原逻辑是先筛选出table1中无法通过postcode匹配table2的记录,再用AL1_POST_TOWN_NAME与table2关联,但table2中同一TOWNNAME对应多条记录,导致结果集膨胀。同时原SQL用MINUS的写法效率较低,可先优化基础查询逻辑。
优化基础查询(替代MINUS)
原SQL的MINUS写法可替换为LEFT JOIN + IS NULL,更高效且能保留table1原有的重复记录:
SELECT x.* FROM table1 x LEFT JOIN table2 u ON x.postcode = u.postcodelocator WHERE u.postcodelocator IS NULL
去重解决方案
1. 直接用DISTINCT去重(仅需保留table1字段时)
如果最终只需要table1的字段,直接在最外层添加DISTINCT即可:
SELECT DISTINCT v.* FROM ( SELECT x.* FROM table1 x LEFT JOIN table2 u ON x.postcode = u.postcodelocator WHERE u.postcodelocator IS NULL ) v LEFT JOIN table2 w ON v.AL1_POST_TOWN_NAME = w.TOWNNAME
2. 用ROW_NUMBER()窗口函数筛选唯一匹配记录
需要保留table2字段,或需指定取哪条匹配记录时,用窗口函数按table1主键分组,给匹配的table2记录排序后取第一条:
SELECT v.*, w.需要的字段 -- 按需添加table2字段 FROM ( SELECT v.*, w.*, ROW_NUMBER() OVER (PARTITION BY v.主键字段 ORDER BY w.主键字段) AS rn FROM ( SELECT x.* FROM table1 x LEFT JOIN table2 u ON x.postcode = u.postcodelocator WHERE u.postcodelocator IS NULL ) v LEFT JOIN table2 w ON v.AL1_POST_TOWN_NAME = w.TOWNNAME ) t WHERE rn = 1
说明:将主键字段替换为table1和table2的实际主键(如id),ORDER BY子句可根据需求选择排序规则(如取最新记录则按创建时间降序)。
3. 提前对table2按TOWNNAME去重
若table2中同一TOWNNAME的记录冗余,可先对table2聚合去重,再进行关联:
SELECT v.*, w.需要的字段 FROM ( SELECT x.* FROM table1 x LEFT JOIN table2 u ON x.postcode = u.postcodelocator WHERE u.postcodelocator IS NULL ) v LEFT JOIN ( SELECT TOWNNAME, MAX(字段1) AS 字段1, -- 用MAX/MIN取唯一值,按需选择 MIN(字段2) AS 字段2 FROM table2 GROUP BY TOWNNAME ) w ON v.AL1_POST_TOWN_NAME = w.TOWNNAME
说明:如果只需TOWNNAME字段,也可用SELECT DISTINCT TOWNNAME FROM table2作为子查询。
内容的提问来源于stack exchange,提问作者user3050151
相关产品推荐
相关产品推荐

