GROUP_CONCAT去重需用DISTINCT关键字,必须紧邻左括号后、字段前,如GROUP_CONCAT(DISTINCT name);SEPARATOR指定分隔符,默认逗号;ORDER BY控制顺序,但不影响去重逻辑;超长内容受group_concat_max_len限制,会静默截断。

GROUP_CONCAT 里怎么去重?
直接用 DISTINCT 关键字,它必须紧挨着 GROUP_CONCAT 的左括号之后、字段之前。不加 DISTINCT 就是原样拼接,重复值照常出现。
常见错误是写成 GROUP_CONCAT(DISTINCT col) AS result 却把 DISTINCT 放错位置(比如写在函数外或字段后),那样会被忽略或报语法错误。
-
GROUP_CONCAT(DISTINCT name)✅ 正确 -
GROUP_CONCAT(name DISTINCT)❌ 语法错误 -
SELECT DISTINCT GROUP_CONCAT(name)❌ 不去重元素,只去重整行结果
如何指定分隔符?
用 SEPARATOR 子句,紧跟在字段表达式后面。默认分隔符是英文逗号 ,,但你可以换成任意字符串,包括空字符串、空格、竖线、甚至换行符 \n(需配合 CONCAT 或客户端处理显示)。
注意:MySQL 8.0+ 和 5.7 对 SEPARATOR 的解析一致,但低版本不支持空字符串作为分隔符(会退化为默认逗号)。
-
GROUP_CONCAT(DISTINCT tag SEPARATOR '|')→ 输出php|js|sql -
GROUP_CONCAT(DISTINCT id SEPARATOR '')→ MySQL 5.7+ 可输出连续数字如1234,5.6 可能仍用逗号 -
GROUP_CONCAT(name SEPARATOR ' > ')→ 适合生成路径类字符串
排序会影响去重和分隔结果吗?
会影响最终字符串的顺序,但不影响去重逻辑本身。ORDER BY 必须写在 SEPARATOR 之后、整个函数闭合前。没排序时,各值顺序由存储引擎扫描顺序决定,不可靠。
特别注意:如果字段含 NULL,GROUP_CONCAT 默认忽略它们;若想保留,得提前用 IFNULL 或 COALESCE 处理,否则排序后可能“消失”得更隐蔽。
GROUP_CONCAT(DISTINCT email ORDER BY email SEPARATOR ';')GROUP_CONCAT(DISTINCT COALESCE(nick, '[unknown]') ORDER BY nick)- 避免
GROUP_CONCAT(DISTINCT col ORDER BY col DESC) SEPARATOR ','——SEPARATOR不能放在ORDER BY后面
长度截断和性能要注意什么?
GROUP_CONCAT 受系统变量 group_concat_max_len 限制,默认 1024 字节。超长部分会被静默截断,不报错也不警告——这是最常被忽略的问题。
临时修改可用 SET SESSION group_concat_max_len = 1000000;永久修改需改 MySQL 配置文件。另外,DISTINCT + ORDER BY 会触发临时表和 filesort,大数据量下可能变慢。
- 查当前限制:
SELECT @@group_concat_max_len - 拼接 JSON 数组风格字符串时,记得手动补上引号和方括号,
GROUP_CONCAT不做任何转义 - 如果字段含特殊字符(如逗号、反斜杠),又没做
REPLACE或JSON_OBJECT包装,下游解析容易出错
DISTINCT、ORDER BY、SEPARATOR 的位置和组合稍有偏差就会失效,而且截断问题往往到上线后查数据不对才暴露。

















