MySQL中GROUP_CONCAT默认截断为1024字符,需调大group_concat_max_len;PostgreSQL中STRING_AGG遇全NULL返回NULL,须用COALESCE兜底,且参数顺序、排序语法与MySQL不兼容。

MySQL 里 GROUP_CONCAT 拼接字符串时结果被截断了
默认只返回 1024 字符,超长部分直接丢弃,不是报错,所以容易误以为数据“没了”。
- 查当前截断长度:
SELECT @@group_concat_max_len; - 临时改大(当前会话有效):
SET SESSION group_concat_max_len = 1000000; - 永久生效需改 MySQL 配置文件
my.cnf,加一行group_concat_max_len = 1000000,然后重启服务 - 注意:
GROUP_CONCAT返回的是TEXT类型,但受该变量限制,不是字段长度问题
PostgreSQL 用 STRING_AGG 拼接,NULL 值导致整组结果变 NULL
STRING_AGG 对任意输入为 NULL 的项不报错,但默认行为是跳过;真正危险的是——如果整组所有值都是 NULL,它返回 NULL 而非空字符串,上游逻辑可能崩。
- 安全写法,强制空字符串兜底:
COALESCE(STRING_AGG(col, ','), '') - 过滤掉 NULL 再拼:
STRING_AGG(COALESCE(col, ''), ',')(注意这会把原NULL变成空字符串) - 排序很重要:
STRING_AGG(col, ',' ORDER BY id),不加ORDER BY结果顺序不确定 - PostgreSQL 9.0+ 才支持
ORDER BY子句,旧版本得先子查询排序
跨数据库写法不兼容:GROUP_CONCAT 和 STRING_AGG 参数顺序相反
看起来都是“字段 + 分隔符”,但参数位置和默认行为差异明显,硬套会出错或静默失败。
- MySQL:
GROUP_CONCAT(col SEPARATOR ',')—— 分隔符用SEPARATOR关键字,不能直接跟逗号 - PostgreSQL:
STRING_AGG(col, ',')—— 分隔符是第二个必填位置参数,无关键字 - MySQL 支持
DISTINCT去重:GROUP_CONCAT(DISTINCT col);PG 需配合子查询或UNIQUE索引逻辑模拟 - 两者都不支持直接在聚合内做条件过滤(比如“只拼 status=1 的”),得用
CASE WHEN转成NULL再进聚合
拼接大量字符串时性能突然变差
不是语法问题,是底层机制:GROUP_CONCAT / STRING_AGG 会在内存中累积结果,数据量大时触发临时磁盘表或 OOM。
- MySQL 中,若结果超
sort_buffer_size,会退化到磁盘临时表,慢得明显 - PG 中,
work_mem设置过小会导致哈希聚合落盘,同样拖慢 - 简单验证:执行前加
EXPLAIN ANALYZE,看是否有Temporary或disk字样 - 真要拼上万行?别硬扛,改成应用层分批查 + 合并,更可控
实际用的时候,最常漏掉的是 MySQL 的 group_concat_max_len 动态调整,还有 PG 里忘记 COALESCE 包一层——这两处不显眼,但一上线就出数据异常。










