SQL Server中针对特定CODE值合并列的实现方法
需求描述
我执行一条SELECT语句后得到如下查询结果:
| S_ID | CODE | C_DESC | CODE_A | C_A_DESC |
|---|---|---|---|---|
| 83597 | PE | PE | PEONESTR | PE ONE STAR |
| 83597 | CE | CE | CEONE | CE ONE STAR |
| 83597 | CE | CE | CERWO | CE TWO STAR |
| 83597 | RG | RG | RGONE | RG ONE STAR |
期望得到如下结果:当CODE列存在多条记录且CODE值为'CE'时,将最后两列的内容分别合并。
| S_ID | CODE | C_DESC | CODE_A | C_A_DESC |
|---|---|---|---|---|
| 83597 | PE | PE | PEONESTR | PE ONE STAR |
| 83597 | CE | CE | CEONE, CERWO | CE ONE STAR, CE TWO STAR |
| 83597 | RG | RG | RGONE | RG ONE STAR |
请问实现该需求的最佳方式是什么?
最佳实现方式
核心思路是按S_ID、CODE、C_DESC分组,对CODE_A和C_A_DESC列执行字符串聚合操作。不同数据库的聚合函数语法有差异,以下是主流数据库的实现方案:
1. MySQL / MariaDB
使用GROUP_CONCAT()函数,默认以逗号分隔,可自定义分隔符:
SELECT S_ID, CODE, C_DESC, GROUP_CONCAT(CODE_A SEPARATOR ', ') AS CODE_A, GROUP_CONCAT(C_A_DESC SEPARATOR ', ') AS C_A_DESC FROM your_table_name GROUP BY S_ID, CODE, C_DESC;
2. PostgreSQL
使用STRING_AGG()函数:
SELECT S_ID, CODE, C_DESC, STRING_AGG(CODE_A, ', ') AS CODE_A, STRING_AGG(C_A_DESC, ', ') AS C_A_DESC FROM your_table_name GROUP BY S_ID, CODE, C_DESC;
3. SQL Server
- 2017及以上版本:直接支持
STRING_AGG():
SELECT S_ID, CODE, C_DESC, STRING_AGG(CODE_A, ', ') AS CODE_A, STRING_AGG(C_A_DESC, ', ') AS C_A_DESC FROM your_table_name GROUP BY S_ID, CODE, C_DESC;
- 2017之前版本:用
STUFF结合FOR XML PATH实现:
SELECT DISTINCT S_ID, CODE, C_DESC, STUFF(( SELECT ', ' + CODE_A FROM your_table_name t2 WHERE t2.S_ID = t1.S_ID AND t2.CODE = t1.CODE AND t2.C_DESC = t1.C_DESC FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, '') AS CODE_A, STUFF(( SELECT ', ' + C_A_DESC FROM your_table_name t2 WHERE t2.S_ID = t1.S_ID AND t2.CODE = t1.CODE AND t2.C_DESC = t1.C_DESC FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, '') AS C_A_DESC FROM your_table_name t1;
4. Oracle(11gR2及以上)
使用LISTAGG()函数:
SELECT S_ID, CODE, C_DESC, LISTAGG(CODE_A, ', ') WITHIN GROUP (ORDER BY CODE_A) AS CODE_A, LISTAGG(C_A_DESC, ', ') WITHIN GROUP (ORDER BY C_A_DESC) AS C_A_DESC FROM your_table_name GROUP BY S_ID, CODE, C_DESC;
补充说明
如果仅需对CODE = 'CE'的记录做聚合,其他CODE保持单条原样,可在聚合函数外层加条件判断(以MySQL为例):
SELECT S_ID, CODE, C_DESC, CASE WHEN CODE = 'CE' THEN GROUP_CONCAT(CODE_A SEPARATOR ', ') ELSE MAX(CODE_A) END AS CODE_A, CASE WHEN CODE = 'CE' THEN GROUP_CONCAT(C_A_DESC SEPARATOR ', ') ELSE MAX(C_A_DESC) END AS C_A_DESC FROM your_table_name GROUP BY S_ID, CODE, C_DESC;
但通常全量分组聚合更通用,能自动处理所有重复CODE的场景。
内容的提问来源于stack exchange,提问作者Eclipse
相关产品推荐
相关产品推荐

