GROUP_CONCAT(MySQL)与STRING_AGG(PostgreSQL/SQL Server 2017+)是语法不兼容的列转行聚合函数:分隔符、排序子句位置、NULL处理及长度限制机制均不同,硬套会报错。

GROUP_CONCAT 和 STRING_AGG 不是同一函数的别名
它们是不同数据库厂商实现的、语义相近但语法不兼容的聚合函数:MySQL 用 GROUP_CONCAT,PostgreSQL 和 SQL Server(2017+)用 STRING_AGG。硬套对方语法会直接报错,比如在 MySQL 里写 STRING_AGG 是 “Unknown function”,在 PostgreSQL 里写 GROUP_CONCAT 是 “Function does not exist”。
分隔符参数位置和强制性差异大
GROUP_CONCAT 的分隔符是可选关键字 SEPARATOR,不写就默认用逗号;STRING_AGG 的分隔符是**必须的第二个参数**,漏掉就会触发签名错误(如 PostgreSQL 报 function string_agg(text) does not exist)。
- MySQL 正确:
GROUP_CONCAT(name SEPARATOR ' | ') - PostgreSQL 正确:
STRING_AGG(name, ' | ') - SQL Server 正确:
STRING_AGG(name, ' | ') WITHIN GROUP (ORDER BY id)
排序子句写法完全不同
GROUP_CONCAT 的 ORDER BY 写在括号内、紧贴字段后;STRING_AGG 在 PostgreSQL 和 SQL Server 中都要求把 ORDER BY(或 WITHIN GROUP (ORDER BY ))作为函数内部子句,且**不能挪到 SELECT 外层**——否则排序对拼接结果完全无效。
- MySQL:
GROUP_CONCAT(name ORDER BY score DESC) - PostgreSQL:
STRING_AGG(name, ', ' ORDER BY score DESC) - SQL Server:
STRING_AGG(name, ', ') WITHIN GROUP (ORDER BY score DESC)
NULL 处理和长度限制机制根本不同
GROUP_CONCAT 默认跳过 NULL 值,但整组无有效值时返回 NULL;更隐蔽的是它受 group_concat_max_len 限制(默认仅 1024 字节),超长部分静默截断,毫无提示。而 STRING_AGG 在 PostgreSQL 中同样跳过 NULL,但无硬长度限制;SQL Server 的 STRING_AGG 则默认把 NULL 当空字符串参与拼接,行为反而更“宽松”。
- 防截断:MySQL 必须先
SET SESSION group_concat_max_len = 1000000 - 防空:所有场景下,只要业务要求非 NULL 返回,就得包一层
COALESCE(STRING_AGG(...), '')或IFNULL(GROUP_CONCAT(...), '') - 类型隐式转换风险:MySQL 的
SEPARATOR支持表达式,但若传入列名会出错;STRING_AGG的分隔符必须是常量,传列名直接报Msg 9836(SQL Server)或类型不匹配(PG)

















