如何编写SQL查询实现数据表中值的归一化?
实现同一ID下的字符串聚合(行转列)
嘿,这个需求其实就是把同一id下的多个name值合并成逗号分隔的字符串,也就是常说的分组字符串聚合,核心逻辑很清晰:先按id字段分组,再对每个分组内的name字段进行字符串拼接。不同SQL方言的实现函数略有区别,我给你整理几个主流数据库的写法:
1. MySQL / MariaDB
用内置的GROUP_CONCAT()函数,这是最直接的写法:
SELECT id, GROUP_CONCAT(name SEPARATOR ',') AS name FROM your_table_name -- 替换成你的实际表名 GROUP BY id;
- 备注:
SEPARATOR ','可以省略,因为默认就是用逗号分隔;如果需要去重,可改成GROUP_CONCAT(DISTINCT name)。
2. PostgreSQL
使用STRING_AGG()函数来完成聚合:
SELECT id, STRING_AGG(name, ',') AS name FROM your_table_name GROUP BY id;
- 备注:同样支持
DISTINCT去重,比如STRING_AGG(DISTINCT name, ','),也可以通过ORDER BY指定拼接顺序,比如STRING_AGG(name, ',' ORDER BY name ASC)。
3. SQL Server
- 2017及以上版本:支持
STRING_AGG(),写法和PostgreSQL类似:
SELECT id, STRING_AGG(name, ',') AS name FROM your_table_name GROUP BY id;
- 2017以下版本:需要用
FOR XML PATH的兼容写法:
SELECT t.id, STUFF((SELECT ',' + name FROM your_table_name WHERE id = t.id FOR XML PATH('')), 1, 1, '') AS name FROM your_table_name t GROUP BY t.id;
- 备注:
FOR XML PATH('')会把子查询的结果拼接成无标签的字符串,STUFF用来去掉开头多余的逗号。
4. Oracle
使用LISTAGG()函数,需要指定拼接顺序:
SELECT id, LISTAGG(name, ',') WITHIN GROUP (ORDER BY name) AS name FROM your_table_name GROUP BY id;
- 备注:
WITHIN GROUP (ORDER BY ...)是必须的,用来定义name值的拼接顺序,你可以换成其他字段(比如ORDER BY id)或者自定义排序规则。
核心逻辑总结
不管用哪种数据库,核心都是两步:
- 用
GROUP BY id把相同ID的行归为一组 - 调用对应数据库的字符串聚合函数,把组内的
name值拼接成单个逗号分隔的字符串
内容的提问来源于stack exchange,提问作者Rahul Kumar
相关产品推荐
相关产品推荐

