json_arrayagg将多行数据聚合成合法json数组,非字符串拼接;必须配合group by使用,默认跳过null,不加order by时顺序不确定,受group_concat_max_len限制。

JSON_ARRAYAGG 会把多行数据聚合成一个 JSON 数组
它不是简单拼字符串,而是生成合法的 JSON 数组(如 [{"id":1},{"id":2}]),直接可用于 API 返回或前端消费。MySQL 5.7+ 和 PostgreSQL 9.5+ 都支持,但行为细节有差异——尤其在空值、NULL 处理和排序控制上容易出错。
不加 ORDER BY 时结果顺序不确定,可能每次查询都不一样
数据库不会保证聚合顺序,除非显式声明。比如 JSON_ARRAYAGG(JSON_OBJECT('id', id, 'name', name)) 若没加 ORDER BY,前端拿到的数组顺序可能随机变动,导致 UI 渲染错乱或 diff 异常。
- MySQL 写法:
JSON_ARRAYAGG(JSON_OBJECT('id', id, 'name', name) ORDER BY id) - PostgreSQL 写法:
JSON_AGG(ROW_TO_JSON(t.*) ORDER BY t.id)(需先构造行对象) - 若想排除 NULL 字段,MySQL 可加
WHERE name IS NOT NULL;PostgreSQL 中JSON_AGG默认跳过 NULL,但ROW_TO_JSON里字段为 NULL 仍会保留键
遇到 NULL 值时 JSON_ARRAYAGG 行为不一致
MySQL 的 JSON_ARRAYAGG 会跳过整行(只要表达式求值为 NULL);PostgreSQL 的 JSON_AGG 同样跳过 NULL 输入,但如果你传入的是 JSON_BUILD_OBJECT('x', col) 且 col 为 NULL,结果里会是 {"x": null},不是跳过。
- 想彻底过滤掉含 NULL 的记录:MySQL 加
HAVING COUNT(*) = COUNT(col)或前置WHERE col IS NOT NULL - PostgreSQL 中更稳妥的是用
FILTER (WHERE col IS NOT NULL)子句(v9.4+) - 聚合空结果集时,MySQL 返回
NULL,PostgreSQL 返回空数组[]——应用层要判断IS NULL或长度
嵌套 JSON_ARRAYAGG 容易触发性能问题或内存溢出
比如在子查询里对每个用户查订单列表,再用外层 JSON_ARRAYAGG 包一层,会导致 N+1 式 JSON 构造,特别是当单个用户有几百条订单时,MySQL 可能报 Packet too large 或超时。
- 优先用 JOIN + 单层聚合,避免多层子查询嵌套
JSON_ARRAYAGG - MySQL 中可设大一点的
group_concat_max_len(它影响 JSON_ARRAYAGG 内部缓冲),但治标不治本 - PostgreSQL 中注意
work_mem设置,聚合大量行时容易撑爆内存
最常被忽略的是:JSON_ARRAYAGG 不是万能“自动转 JSON”开关,它的输入必须是合法 JSON 片段(如 JSON_OBJECT、JSON_QUOTE 或已校验过的字段),直接塞字符串或数字可能触发隐式转换失败,尤其当字段含特殊字符或二进制内容时。











