mysql 8.0+ 中 group_concat 必须显式使用 distinct 和 order by 才能去重并排序,正确写法为 group_concat(distinct col order by col separator ','),distinct 必须在 order by 前;默认分隔符为逗号,超长(默认1024字符)会截断,需 set session group_concat_max_len 调整;postgresql 和 sql server 的对应函数均不原生支持 distinct,须依赖子查询或 cte 预处理。

MySQL 8.0+ 用 GROUP_CONCAT 配合 DISTINCT 和 ORDER BY
直接用 GROUP_CONCAT 就能搞定,但必须显式加 DISTINCT 和 ORDER BY,否则重复项不会去重,顺序也不保证。
常见错误是写成 GROUP_CONCAT(col) 然后在外面套 DISTINCT ——没用,GROUP_CONCAT 自身才支持去重。
-
GROUP_CONCAT(DISTINCT col ORDER BY col SEPARATOR ',')是标准写法,DISTINCT必须在ORDER BY前面 - 分隔符默认是逗号,想用其他(比如竖线)就改
SEPARATOR '|' - 如果拼接结果超长(默认 1024 字符),会截断,需提前设
SET SESSION group_concat_max_len = 10000;
PostgreSQL 用 STRING_AGG + DISTINCT + ORDER BY
PostgreSQL 不支持 STRING_AGG 内置 DISTINCT,得靠子查询或 UNIQUE 排序前去重。
最稳妥写法是先 DISTINCT ON 或用子查询过滤重复值,再进 STRING_AGG。
-
STRING_AGG(col, ',' ORDER BY col)本身不处理重复,必须前置去重 - 推荐:
STRING_AGG(sub.col, ',' ORDER BY sub.col)+(SELECT DISTINCT col FROM t2 WHERE t2.group_id = t1.id) AS sub - 注意:
DISTINCT ON (col)在窗口里容易出错,不如明确子查询清晰
SQL Server 用 STRING_AGG(2017+)或 FOR XML(旧版本)
2017 及以上可用 STRING_AGG,但它也不原生支持 DISTINCT,得配合 GROUP BY 或子查询。
老版本只能用 FOR XML PATH('') 拼接,但去重和排序更麻烦,容易漏掉空值或特殊字符。
-
STRING_AGG(col, ',') WITHIN GROUP (ORDER BY col)仅排序,不去重 - 去重必须在外层或 CTE 中先
SELECT DISTINCT,例如:SELECT STRING_AGG(name, ',') WITHIN GROUP (ORDER BY name) FROM (SELECT DISTINCT name FROM t) AS dedup -
FOR XML方式要手动REPLACE开头逗号,且&、会被转义,得额外处理
SQLite 没有内置聚合去重函数,得靠 GROUP BY + 聚合模拟
SQLite 的 GROUP_CONCAT 和 MySQL 一样支持 ORDER BY,但**不支持 DISTINCT 关键字**——这是最容易踩的坑。
必须用子查询或 CTE 先去重,否则重复值照常拼进去。
- 写法示例:
SELECT GROUP_CONCAT(name, ',') FROM (SELECT DISTINCT name FROM t WHERE group_id = ? ORDER BY name) - 不能写成
GROUP_CONCAT(DISTINCT name, ',')—— SQLite 会报错或忽略DISTINCT - 如果数据量大,子查询可能影响性能,考虑加
(group_id, name)复合索引











