如何通过JSON_ARRAYAGG函数在MySQL中将多行JSON数据合并成单一JSON数组?
- 内容介绍
- 文章标签
- 相关推荐
本文共计714个文字,预计阅读时间需要3分钟。
如果您在查询结果中遇到`NULL`和`JSON_ARRAYAGG`,这通常意味着查询返回了空的结果集。下面是对这种情况的简单解释:
常见做法是用 WHERE 过滤掉空值,或者用 IFNULL / COALESCE 替换:
SELECT JSON_ARRAYAGG( JSON_OBJECT('id', id, 'name', name) ) FROM users WHERE id IS NOT NULL AND name IS NOT NULL;
如果必须保留行但不想让 NULL 进数组,得先转换——比如用 IF(id IS NULL, NULL, JSON_OBJECT(...)) 再配合 WHERE ... IS NOT NULL 二次过滤。
JSON_ARRAYAGG 必须配合 GROUP BY,否则默认聚合成一行
单独写 SELECT JSON_ARRAYAGG(json_col) FROM table 是合法的,但它把整张表所有行压成一个数组。多数时候你其实想按某个维度分组聚合,比如“每个 category 对应一个 JSON 数组”。
这时候漏写 GROUP BY 就会得到意外的单条结果,而不是你预期的多行分组结果:
- 要分组:加
GROUP BY category,每组返回一行,JSON_ARRAYAGG聚合该组内所有记录 - 不分组:全表聚合为一条记录,
JSON_ARRAYAGG返回一个大数组 - 没加
GROUP BY却在 SELECT 里混用了普通列(如SELECT category, JSON_ARRAYAGG(...)),MySQL 8.0+ 会报错Expression #1 of SELECT list is not in GROUP BY clause
嵌套 JSON_OBJECT 和 JSON_ARRAYAGG 容易引号逃逸混乱
手拼 JSON 字符串(比如用 CONCAT('{"items":', JSON_ARRAYAGG(...), '}'))非常危险:内部 JSON 的双引号不会被自动转义,最终得到非法 JSON。
正确方式永远优先用 JSON 函数组合:
SELECT JSON_OBJECT( 'category', category, 'items', JSON_ARRAYAGG(JSON_OBJECT('id', id, 'title', title)) ) FROM posts GROUP BY category;
这样 MySQL 自动处理嵌套结构和引号转义。一旦看到 CONCAT + JSON_ARRAYAGG 混用,基本可以判定输出不可靠。
大数据量下 JSON_ARRAYAGG 可能触发 group_concat_max_len 截断
JSON_ARRAYAGG 底层复用 group_concat 的缓冲机制,受系统变量 group_concat_max_len 限制。默认值通常是 1024,远不够存多个 JSON 对象。
查当前值:SELECT @@group_concat_max_len;
临时调高(当前会话):SET SESSION group_concat_max_len = 1000000;
注意:这个设置只对当前连接生效;如果用连接池,得在每次获取连接后执行 SET,或直接改全局配置(需权限)。
另外,超长 JSON 不仅可能被截断,还会显著拖慢查询——建议在应用层分页聚合,而不是一次拉几十万条进一个 JSON 数组。
本文共计714个文字,预计阅读时间需要3分钟。
如果您在查询结果中遇到`NULL`和`JSON_ARRAYAGG`,这通常意味着查询返回了空的结果集。下面是对这种情况的简单解释:
常见做法是用 WHERE 过滤掉空值,或者用 IFNULL / COALESCE 替换:
SELECT JSON_ARRAYAGG( JSON_OBJECT('id', id, 'name', name) ) FROM users WHERE id IS NOT NULL AND name IS NOT NULL;
如果必须保留行但不想让 NULL 进数组,得先转换——比如用 IF(id IS NULL, NULL, JSON_OBJECT(...)) 再配合 WHERE ... IS NOT NULL 二次过滤。
JSON_ARRAYAGG 必须配合 GROUP BY,否则默认聚合成一行
单独写 SELECT JSON_ARRAYAGG(json_col) FROM table 是合法的,但它把整张表所有行压成一个数组。多数时候你其实想按某个维度分组聚合,比如“每个 category 对应一个 JSON 数组”。
这时候漏写 GROUP BY 就会得到意外的单条结果,而不是你预期的多行分组结果:
- 要分组:加
GROUP BY category,每组返回一行,JSON_ARRAYAGG聚合该组内所有记录 - 不分组:全表聚合为一条记录,
JSON_ARRAYAGG返回一个大数组 - 没加
GROUP BY却在 SELECT 里混用了普通列(如SELECT category, JSON_ARRAYAGG(...)),MySQL 8.0+ 会报错Expression #1 of SELECT list is not in GROUP BY clause
嵌套 JSON_OBJECT 和 JSON_ARRAYAGG 容易引号逃逸混乱
手拼 JSON 字符串(比如用 CONCAT('{"items":', JSON_ARRAYAGG(...), '}'))非常危险:内部 JSON 的双引号不会被自动转义,最终得到非法 JSON。
正确方式永远优先用 JSON 函数组合:
SELECT JSON_OBJECT( 'category', category, 'items', JSON_ARRAYAGG(JSON_OBJECT('id', id, 'title', title)) ) FROM posts GROUP BY category;
这样 MySQL 自动处理嵌套结构和引号转义。一旦看到 CONCAT + JSON_ARRAYAGG 混用,基本可以判定输出不可靠。
大数据量下 JSON_ARRAYAGG 可能触发 group_concat_max_len 截断
JSON_ARRAYAGG 底层复用 group_concat 的缓冲机制,受系统变量 group_concat_max_len 限制。默认值通常是 1024,远不够存多个 JSON 对象。
查当前值:SELECT @@group_concat_max_len;
临时调高(当前会话):SET SESSION group_concat_max_len = 1000000;
注意:这个设置只对当前连接生效;如果用连接池,得在每次获取连接后执行 SET,或直接改全局配置(需权限)。
另外,超长 JSON 不仅可能被截断,还会显著拖慢查询——建议在应用层分页聚合,而不是一次拉几十万条进一个 JSON 数组。

