UNION含重复条目表时,如何生成带拼接表标识的合并列?
解决UNION合并时拼接表标识的问题
你遇到的核心问题是:直接给UNION的结果加表标识列会让原本内容重复的行因为标识不同而被当成唯一行保留,而你需要把内容相同的行合并,同时把它们所属的表标识拼接起来。下面是针对SQL Server(你示例使用的环境)的具体解决方案,也会补充其他数据库的适配方式。
具体实现步骤
1. 先合并带表标识的所有行
首先用UNION ALL把两张表的数据都带上各自的表标识('A'和'B'),注意这里用UNION ALL而不是UNION——因为UNION会自动去重,会丢失我们需要的表归属信息,而UNION ALL会保留所有原始行:
SELECT 'A' AS tablename, Column1, Column2 FROM TableA UNION ALL SELECT 'B' AS tablename, Column1, Column2 FROM TableB
2. 分组聚合拼接表标识
接下来对上面的结果按Column1和Column2分组,用字符串聚合函数把同一组的表标识拼接起来。在SQL Server 2017及以上版本,可以用STRING_AGG函数:
SELECT STRING_AGG(tablename, '') WITHIN GROUP (ORDER BY tablename) AS tablename, Column1, Column2 FROM ( -- 子查询就是第一步的合并结果 SELECT 'A' AS tablename, Column1, Column2 FROM TableA UNION ALL SELECT 'B' AS tablename, Column1, Column2 FROM TableB ) AS combined_data GROUP BY Column1, Column2
这个查询会输出你想要的结果:
- 对于在两张表中都存在的行(比如
Foo, Bar),tablename会被拼接成AB - 只存在于TableA的行(比如
Donut, Onions),tablename为A - 只存在于TableB的行(比如
Donut, Pickles),tablename为B
适配其他数据库的写法
如果你的数据库不是SQL Server,可以用对应的字符串聚合函数:
- MySQL/MariaDB:用
GROUP_CONCAT,记得加DISTINCT避免同一张表内重复行导致标识重复:
SELECT GROUP_CONCAT(DISTINCT tablename ORDER BY tablename SEPARATOR '') AS tablename, Column1, Column2 FROM ( SELECT 'A' AS tablename, Column1, Column2 FROM TableA UNION ALL SELECT 'B' AS tablename, Column1, Column2 FROM TableB ) AS combined_data GROUP BY Column1, Column2;
- Oracle:用
LISTAGG函数:
SELECT LISTAGG(tablename, '') WITHIN GROUP (ORDER BY tablename) AS tablename, Column1, Column2 FROM ( SELECT 'A' AS tablename, Column1, Column2 FROM TableA UNION ALL SELECT 'B' AS tablename, Column1, Column2 FROM TableB ) AS combined_data GROUP BY Column1, Column2;
关键注意点
- 必须用
UNION ALL:如果用UNION,会自动去掉内容重复的行,导致无法收集到所有表标识信息 - 聚合时排序:通过
WITHIN GROUP (ORDER BY tablename)可以保证拼接顺序是A在前B在后,避免出现BA的情况 - 处理单表内重复:如果同一张表中存在重复的
Column1+Column2行,记得在聚合函数里加DISTINCT(比如MySQL的GROUP_CONCAT),避免标识重复拼接(比如变成AA)
内容的提问来源于stack exchange,提问作者Ksdmg
相关产品推荐
相关产品推荐

