字符串聚合是什么
string_agg 是 PostgreSQL 的字符串聚合函数:把分组内多行的文本按指定分隔符拼成一个字符串,还支持 DISTINCT 与 ORDER BY。MySQL 的对应函数是 GROUP_CONCAT,用途相同,但参数顺序与写法差异明显,是迁移时最容易出错的函数之一。
基本信息
| PostgreSQL 语法 | string_agg(表达式, 分隔符 [ORDER BY …]) |
|---|---|
| MySQL 语法 | GROUP_CONCAT(表达式 [ORDER BY …] SEPARATOR '分隔符') |
| 去重 | 两者都支持 DISTINCT |
| 分隔符位置 | PG 是第二个参数;MySQL 用 SEPARATOR 关键字写在末尾 |
| 长度限制 | MySQL 受 group_concat_max_len 约束,PG 受字段类型上限约束 |
典型使用场景
- 把同一用户的多个商品名拼成一行展示
- 把分组内的标签汇总成逗号列表
- 报表里输出「参与人」名单
- 导出数据时把明细折叠进一个单元格
- 按业务顺序拼接,例如按时间排列操作记录
PostgreSQL 写法
PostgreSQL 写法
-- 去重并按名称排序后拼接
SELECT user_id,
string_agg(DISTINCT product_name, ', ' ORDER BY product_name) AS products
FROM order_items
GROUP BY user_id;
-- 按时间顺序拼接
SELECT order_id,
string_agg(item_name, ' / ' ORDER BY created_at) AS items
FROM order_items
GROUP BY order_id;MySQL 写法
MySQL 写法
-- ORDER BY 写在表达式之后,SEPARATOR 写在最后
SELECT user_id,
GROUP_CONCAT(DISTINCT product_name ORDER BY product_name SEPARATOR ', ') AS products
FROM order_items
GROUP BY user_id;
-- 默认分隔符是逗号;长度上限受参数控制,超长会被截断
SELECT @@group_concat_max_len;两库对照
| 维度 | PostgreSQL string_agg | MySQL GROUP_CONCAT |
|---|---|---|
| 分隔符 | 函数第二个参数 | SEPARATOR 关键字放末尾 |
| 排序 | 函数内写 ORDER BY | 表达式之后写 ORDER BY |
| 去重 | 支持 DISTINCT | 支持 DISTINCT |
| 长度限制 | 受字段类型上限约束 | 受 group_concat_max_len 约束,超长截断 |
| 拼接顺序 | 需显式 ORDER BY 才确定 | 同样需要显式 ORDER BY |
MySQL 的 GROUP_CONCAT 超过 group_concat_max_len 会被静默截断、不报错:拼出来的列表少了一截,下游很难发现。拼接长列表前先确认该参数,必要时在当前会话临时调大。
不写 ORDER BY 时拼接顺序不保证:即使当前看起来是按插入顺序输出,执行计划一变顺序就可能不同。需要确定顺序就显式排序。
拼接结果只适合展示:它既不适合做过滤条件,也不适合当关联键,除了顺序不稳定,分隔符还可能和数据本身冲突(商品名里就带逗号),需要时改用更少见的分隔符。
两库都支持对拼接结果排序:PostgreSQL 的 ORDER BY 写在函数内,MySQL 写在表达式之后,位置不同但语义一致,迁移时最容易漏改这一处。