SQL执行UNION时能否忽略指定列判断行的唯一性?
问题解答
UNION能否仅按指定列去重?
- 不能。UNION的去重逻辑是对合并后结果集的所有列的整体组合值做唯一性校验,只要任意一列的值存在差异,两行就会被判定为不同数据,无法单独指定仅按某几列完成去重。
替代实现方案
你可以先通过UNION ALL合并所有查询结果(UNION ALL不会执行去重操作,性能比UNION更高),再基于去重规则做过滤即可,针对你的场景推荐两种常用实现:
方案1:窗口函数实现(推荐,可灵活控制保留行规则)
可以通过ROW_NUMBER()窗口函数按需要去重的列分区,每个分区仅取1行即可,示例代码如下:
WITH union_all_result AS ( -- 你的第1个查询 SELECT d.id, d.registration_number, d.col1, d.col2, d.col3, d.col4 -- 另外4个不需要参与去重的列 FROM DOCUMENTS d UNION ALL -- 你的第2个查询 SELECT dd.id, dd.registration_number, dd.col1, dd.col2, dd.col3, dd.col4 FROM DIFFERENT_DOCUMENTS dd UNION ALL -- 剩下3个查询依次往下加即可 SELECT ... ) SELECT id, registration_number, col1, col2, col3, col4 FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY registration_number -- 按需要去重的列分区 ORDER BY id -- 这里可以自定义保留规则,比如优先保留id更小的行、优先保留某张表的行都可以调整 ) AS rn FROM union_all_result ) t WHERE rn = 1;
如果需要优先保留某张来源表的行,可以在每个子查询里新增优先级字段,比如第一个查询加1 as sort_priority,第二个加2 as sort_priority,窗口函数的ORDER BY改成sort_priority ASC即可。
方案2:GROUP BY聚合实现(适配不支持窗口函数的低版本数据库)
如果你的数据库不支持窗口函数,可以通过GROUP BY分组加聚合函数实现,缺点是无法灵活控制非分组列的取值来源,只能通过聚合规则取最大/最小值等:
SELECT MIN(id) AS id, -- 非去重列通过聚合函数取值 registration_number, MIN(col1) AS col1, MAX(col2) AS col2 -- 聚合规则可以根据你的需要调整 FROM ( -- 这里放所有UNION ALL合并的查询,和方案1的union_all_result内容一致 SELECT d.id, d.registration_number, d.col1, d.col2, d.col3, d.col4 FROM DOCUMENTS d UNION ALL SELECT dd.id, dd.registration_number, dd.col1, dd.col2, dd.col3, dd.col4 FROM DIFFERENT_DOCUMENTS dd UNION ALL ... -- 剩余查询 ) t GROUP BY registration_number;
场景适配说明
你当前的场景总数据量只有100行左右,两种方案的性能没有明显差异,可根据自己的数据库版本和取值需求选择即可。
内容的提问来源于stack exchange,提问作者vr552
相关产品推荐
相关产品推荐

