SQL Union查询同ID行替换:B表ID存在时覆盖A表值如何实现
需求实现方案
这个需求完全可以实现,你当前使用UNION的方式仅会对整行完全一致的结果去重,不会按ID维度做优先级筛选,因此返回了两行数据,可以使用以下两种常用方案实现需求:
- 方案一:
NOT IN匹配法(兼容性最高,适合所有SQL环境)
逻辑为全量取B表数据,再补充A表中ID没有出现在B表中的数据即可,示例代码如下:
-- 实际业务场景直接替换为你的A、B表名即可 SELECT id, "user" FROM B UNION ALL SELECT id, "user" FROM A WHERE A.id NOT IN (SELECT id FROM B)
对应你给出的测试用例写法:
SELECT id, "user" FROM (select '1' as id, 'Alice' as "user" from dual) B UNION ALL SELECT id, "user" FROM (select '1' as id, 'Bob' as "user" from dual) A WHERE A.id NOT IN (SELECT id FROM (select '1' as id, 'Alice' as "user" from dual) B)
该方案逻辑直观,只要ID字段建立了索引,查询性能很高。
- 方案二:窗口函数排序法(适合支持窗口函数的SQL环境,如MySQL 8.0+、PostgreSQL、Oracle 11g+等)
逻辑为给两个表的数据添加优先级标记,B表优先级高于A表,同ID按优先级倒序排序后取第一条即可,示例代码如下:
WITH all_data AS ( SELECT *, 2 AS priority FROM B UNION ALL SELECT *, 1 AS priority FROM A ) SELECT id, "user" FROM ( SELECT id, "user", ROW_NUMBER() OVER (PARTITION BY id ORDER BY priority DESC) AS rn FROM all_data ) t WHERE rn = 1;
该方案适合表字段较多的场景,不需要重复写多个字段的匹配逻辑,扩展性更强。
以上两种方案执行后都会返回你预期的1 Alice的结果。
内容的提问来源于stack exchange,提问作者user5507535
相关产品推荐
相关产品推荐

