SQL中按相同名称合并多行数据?我的语句为何结果异常?
SQL聚合课程结果异常的排查与解决
嘿,我帮你找到问题根源啦!你遇到的每个用户都显示所有课程的问题,核心原因是没有按用户(WM字段)正确分组,导致字符串聚合函数把表中所有行的Class值都拼接在一起了。
先理清楚你的数据(补全你给出的插入语句)
先把你没写完的插入语句补全,方便后续测试:
INSERT INTO T (ID, WM, Class, Prof) VALUES (NULL, 'Adam', 'Math', 'Sam'), (1, 'Adam', 'Science', 'Lee'), (2, 'Tony', 'Math', 'Sam'), (3, 'Erica', 'English', 'Clark'), (3, 'Erica', 'History', 'Lewis');
错误原因分析
如果你之前写的SQL类似下面这样(没有分组或分组错误),就会出现全量课程的问题:
-- 错误示例:没有GROUP BY,或者GROUP BY的字段不对 SELECT ID, WM, GROUP_CONCAT(Class SEPARATOR ', ') AS Classes FROM T;
这种情况下,数据库会把整个表当成一个分组,自然会把所有课程都拼在一起。
针对不同数据库的正确SQL语句
根据你使用的数据库类型,选择对应的语句,核心是按WM(用户名)分组,同时处理ID的NULL问题(Adam有一条ID为NULL的记录):
1. MySQL/MariaDB
使用GROUP_CONCAT函数:
SELECT COALESCE(MAX(ID), 0) AS ID, -- 取用户的非NULL最大ID,全NULL则用0兜底 WM, GROUP_CONCAT(DISTINCT Class SEPARATOR ', ') AS Classes FROM T GROUP BY WM ORDER BY ID;
2. SQL Server/Azure SQL
使用STRING_AGG函数:
SELECT COALESCE(MAX(ID), 0) AS ID, WM, STRING_AGG(DISTINCT Class, ', ') WITHIN GROUP (ORDER BY Class) AS Classes FROM T GROUP BY WM ORDER BY ID;
3. PostgreSQL
同样使用STRING_AGG函数:
SELECT COALESCE(MAX(ID), 0) AS ID, WM, STRING_AGG(DISTINCT Class, ', ' ORDER BY Class) AS Classes FROM T GROUP BY WM ORDER BY ID;
关键注意点
- 一定要按
WM分组:这是让聚合函数只处理每个用户自己课程的核心。 - 处理ID的NULL:因为Adam有一条ID为NULL的记录,用
MAX(ID)可以拿到该用户的有效ID,COALESCE避免出现NULL的ID结果。 - 不需要去重就删
DISTINCT:如果你的业务里同一个用户不会重复选同一门课,可以去掉DISTINCT关键字,提升效率。
执行上述正确语句后,就能得到你预期的输出:
1 | Adam | Math, Science 2 | Tony | Math 3 | Erica | English, History
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

