MySQL、PostgreSQL、SQL Server 的拼接函数均要求排序必须在函数内部显式声明,外部 ORDER BY 无效;三者在语法结构、NULL 处理、分隔符位置、去重方式及长度限制等方面互不兼容。

MySQL 用 GROUP_CONCAT 拼接并排序,必须显式加 ORDER BY 子句
MySQL 不支持在 GROUP_CONCAT 外部用 ORDER BY 影响拼接顺序——排序必须写在函数内部。否则结果顺序不可靠,尤其在有索引或数据量变化时容易出错。
-
GROUP_CONCAT(name ORDER BY created_at DESC):按时间倒序拼接 -
GROUP_CONCAT(DISTINCT status ORDER BY status):去重 + 字典序升序 - 默认分隔符是逗号(
,),可用SEPARATOR ' | '自定义,如GROUP_CONCAT(name ORDER BY id SEPARATOR ' → ') - 注意长度限制:
GROUP_CONCAT默认最大长度是 1024 字符,超长会被截断;需临时调整系统变量:SET SESSION group_concat_max_len = 10000;
PostgreSQL 用 STRING_AGG 拼接并排序,ORDER BY 是必需参数
PostgreSQL 的 STRING_AGG 要求显式声明排序逻辑,不提供默认顺序,漏写 ORDER BY 会报错:ERROR: function string_agg(text) does not exist(因缺少排序参数导致签名不匹配)。
- 正确写法:
STRING_AGG(name, ', ' ORDER BY score DESC) - 分隔符是第二个参数,必须是字符串字面量或表达式,不能省略
- 支持
DISTINCT,但须放在ORDER BY前:STRING_AGG(DISTINCT tag, ', ' ORDER BY tag) - 若字段可能为 NULL,
STRING_AGG默认跳过,无需额外处理;但想保留空字符串占位,得先用COALESCE(tag, '')
SQL Server 用 STRING_AGG(2017+)拼接时,ORDER BY 必须紧跟在函数内
SQL Server 的 STRING_AGG 语法和 PostgreSQL 类似,但对空值更敏感:默认把 NULL 当作空字符串参与拼接,不像 PG 那样自动过滤。
- 基本形式:
STRING_AGG(name, '; ') WITHIN GROUP (ORDER BY updated_at) -
WITHIN GROUP (ORDER BY ...)是强制语法结构,不能写成函数外的ORDER BY - 若要排除 NULL,需提前过滤:
STRING_AGG(CASE WHEN name IS NOT NULL THEN name END, '; ') WITHIN GROUP (ORDER BY id),注意此时可能产生多余分隔符,建议配合WHERE name IS NOT NULL - 聚合前建议加
ISNULL(name, '')统一空值表现,避免意外空白项
跨数据库兼容性差,别指望一个 SQL 脚本通吃
三个主流数据库的拼接函数不仅名字不同,参数位置、NULL 处理、去重语法、长度限制机制全都不一致。哪怕只是加个排序,写法也完全割裂。
实际项目中如果需要切换数据库,最稳妥的方式是:在应用层做拼接(如 Python 的 ' | '.join([x.name for x in rows])),或者封装数据库特定的视图/函数,而不是在 SQL 层强求统一写法。尤其当排序依据是动态字段或带条件时,SQL 层拼接很快会变得难读难维护。










