如何用SQL将同一用户的多行enrolment_value合并为单行?
将同一用户的enrolment_value合并到同一行的SQL方案
这个需求完全可行,核心是利用各数据库提供的字符串聚合函数,结合GROUP BY user_id来实现。以下是主流数据库的具体实现方案:
MySQL(5.7及以上版本)
使用GROUP_CONCAT函数,支持自定义分隔符,还可添加DISTINCT去重重复值:
SELECT user_id, GROUP_CONCAT(enrolment_value SEPARATOR ', ') AS combined_enrolment_values FROM enrolments GROUP BY user_id;
如果需要去重:
SELECT user_id, GROUP_CONCAT(DISTINCT enrolment_value SEPARATOR ', ') AS combined_enrolment_values FROM enrolments GROUP BY user_id;
PostgreSQL
使用STRING_AGG函数,语法简洁:
SELECT user_id, STRING_AGG(enrolment_value, ', ') AS combined_enrolment_values FROM enrolments GROUP BY user_id;
去重写法:
SELECT user_id, STRING_AGG(DISTINCT enrolment_value, ', ') AS combined_enrolment_values FROM enrolments GROUP BY user_id;
SQL Server
- 2017及以上版本:直接用
STRING_AGG
SELECT user_id, STRING_AGG(enrolment_value, ', ') AS combined_enrolment_values FROM enrolments GROUP BY user_id;
- 旧版本(2016及以下):用
STUFF + FOR XML PATH模拟字符串聚合
SELECT user_id, STUFF(( SELECT ', ' + enrolment_value FROM enrolments e2 WHERE e2.user_id = e1.user_id FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, '') AS combined_enrolment_values FROM enrolments e1 GROUP BY user_id;
Oracle
使用LISTAGG函数,还可指定排序规则:
SELECT user_id, LISTAGG(enrolment_value, ', ') WITHIN GROUP (ORDER BY enrolment_value) AS combined_enrolment_values FROM enrolments GROUP BY user_id;
Oracle 12c及以上支持去重:
SELECT user_id, LISTAGG(DISTINCT enrolment_value, ', ') WITHIN GROUP (ORDER BY enrolment_value) AS combined_enrolment_values FROM enrolments GROUP BY user_id;
补充说明
你之前用GROUP BY仅得到单条记录,是因为没有对enrolment_value使用聚合函数——GROUP BY会将同一user_id的行合并为一组,必须通过聚合函数(比如上面的字符串聚合函数)来处理组内的enrolment_value,否则数据库会报错或返回组内随机一条值(取决于数据库配置)。
内容的提问来源于stack exchange,提问作者Mohsin A.
相关产品推荐
相关产品推荐

