Oracle全外连接结果去重:剔除存在非Null的Null重复行
解决Oracle全外连接后冗余Null行的清理问题
看来你已经试过直接分组处理,但没达到预期效果。咱们直接针对你的规则来写SQL,核心思路就是先判断每个值是否存在非Null的关联记录,再决定要不要保留对应的Null行。
方案一:用窗口函数(推荐,效率更高)
这个方法只需要一次全外连接,通过窗口函数标记每个值的关联情况,最后过滤掉冗余行:
WITH joined_data AS ( SELECT t1.ColumnFromTable1, t2.ColumnFromTable2, -- 统计当前ColumnFromTable1有多少非Null的ColumnFromTable2关联 COUNT(t2.ColumnFromTable2) OVER (PARTITION BY t1.ColumnFromTable1) AS has_non_null_t2, -- 统计当前ColumnFromTable2有多少非Null的ColumnFromTable1关联 COUNT(t1.ColumnFromTable1) OVER (PARTITION BY t2.ColumnFromTable2) AS has_non_null_t1 FROM Table1 t1 FULL OUTER JOIN Table2 t2 ON t1.common_code = t2.common_code ) SELECT ColumnFromTable1, ColumnFromTable2 FROM joined_data WHERE -- 处理Table1有值的情况:要么关联的Table2值非Null,要么没有任何非Null关联(保留Null) (ColumnFromTable1 IS NOT NULL AND (ColumnFromTable2 IS NOT NULL OR has_non_null_t2 = 0)) -- 处理Table1无值的情况:只有当Table2的值没有任何非Null关联时才保留 OR (ColumnFromTable1 IS NULL AND has_non_null_t1 = 0);
方案二:用EXISTS子查询
如果对窗口函数不太熟悉,也可以用EXISTS来判断是否存在关联记录,逻辑完全一致:
SELECT t1.ColumnFromTable1, t2.ColumnFromTable2 FROM Table1 t1 FULL OUTER JOIN Table2 t2 ON t1.common_code = t2.common_code WHERE -- Table1有值的情况:要么Table2值非Null,要么该值没有任何Table2关联 (t1.ColumnFromTable1 IS NOT NULL AND (t2.ColumnFromTable2 IS NOT NULL OR NOT EXISTS (SELECT 1 FROM Table2 t2_sub WHERE t2_sub.common_code = t1.common_code))) -- Table1无值的情况:该Table2值没有任何Table1关联 OR (t1.ColumnFromTable1 IS NULL AND NOT EXISTS (SELECT 1 FROM Table1 t1_sub WHERE t1_sub.common_code = t2.common_code));
对应你的示例数据验证
用你给出的结果测试这两个方案:
AAA Null会被过滤:因为AAA存在非Null的关联行(ABA、ACC),has_non_null_t2=2≠0Null FFF会被过滤:因为FFF存在非Null的关联行(DDD、GGG),has_non_null_t1=2≠0BBB Null和Null EFE会保留:因为它们没有对应的非Null关联行
最终就能得到你期望的清理后的结果。
内容的提问来源于stack exchange,提问作者jeff
相关产品推荐
相关产品推荐

