首页/数据/SQL 速查/JSON 聚合:JSON_ARRAYAGG 与 json_agg
聚合与窗口函数54 条

JSON 聚合:JSON_ARRAYAGG 与 json_agg

把组内数据聚合成 JSON 数组/对象,接口直接消费;MySQL 8 用 JSON_ARRAYAGG/JSON_OBJECTAGG,PostgreSQL 用 json_agg/jsonb_object_agg。

SQL 速查数据更新于 2026-10-13

把分组数据聚合成 JSON

接口经常需要一个对象带一个数组的结构,例如用户详情里带上他买过的商品名列表。这类结构在数据库侧就能拼好,省掉应用层再组装一次。MySQL 8 提供数组聚合与键值聚合两个函数;PostgreSQL 对应的是 json 与 jsonb 两套聚合函数。两边的差异集中在两点:元素顺序能不能在聚合里指定,以及空值是否进入结果数组。

基本信息

适用平台MySQL 8.0 / PostgreSQL 12 及以上
MySQL 函数数组聚合函数与键值对象聚合函数各一个
PostgreSQL 函数json 与 jsonb 各有一组,对象聚合另有专门函数
排序能力PostgreSQL 可在聚合内部直接指定元素顺序
结果类型PostgreSQL 的 jsonb 会做键标准化与去重,输出顺序不保留

典型使用场景

  • 用户详情接口返回该用户购买过的商品名数组
  • 订单列表页给每个订单带上明细条目,避免逐单再查一次
  • 把多行标签聚合成一个数组字段,直接写入缓存或搜索结果
  • 构建键值映射:按类型字段聚合出「类型到数量」的对象
  • 报表导出时把多行明细压成一行 JSON,便于前端直接渲染

两库聚合示例

两库聚合示例
-- MySQL 8:把每个用户的商品名聚合成数组
SELECT user_id,
       JSON_ARRAYAGG(product_name) AS products
FROM order_items
GROUP BY user_id;

-- MySQL 8:按名称聚合出键值对象(键重复时后面的覆盖前面的)
SELECT JSON_OBJECTAGG(product_name, qty) AS kv
FROM order_items WHERE user_id = 100;

-- PostgreSQL:聚合内部可以直接指定顺序
SELECT user_id,
       json_agg(product_name ORDER BY product_name) AS products
FROM order_items
GROUP BY user_id;

-- PostgreSQL:键值对象聚合
SELECT jsonb_object_agg(product_name, qty) AS kv
FROM order_items WHERE user_id = 100;

差异要点

对比项MySQLPostgreSQL
数组聚合提供数组聚合函数json 与 jsonb 两套,jsonb 更适合索引与比较
对象聚合提供键值聚合函数提供键值聚合函数,空键会报错
元素顺序聚合内不能指定,需先在子查询里排序可在聚合内直接指定顺序
空值处理两库行为不同,需用样例数据核对jsonb 输出会重排键,顺序不保留
结果可用性结果是合法的 JSON 文本jsonb 可继续用运算符做筛选
排序这件事不要想当然:MySQL 的数组聚合不保证元素顺序,需要固定顺序时先在子查询里排好再聚合,并且用样例数据验证实际输出顺序;PostgreSQL 则可以直接把排序写进聚合表达式。
聚合结果可能很大。给接口一次性返回上万条明细会让 JSON 文本膨胀到几兆,网络传输与前端解析都吃不消,通常应限制条数或改为分页获取明细。

易错点

  • 以为数组聚合会自动按某列排序:MySQL 不保证顺序,未显式处理时接口输出顺序会漂移
  • 空值处理两库不同(是否进入数组、是否拼成 null),对接接口前用样例数据核对输出内容
  • 键值聚合适用键重复的数据:后出现的值会覆盖前面的,先确认按键是否唯一
  • 拿聚合结果直接做等值筛选:JSON 文本的空白与键顺序都可能不同,比较很难命中
  • 把大结果集的明细全部聚合成 JSON 返回,接口响应体积失控,应设上限

数据来源与参考

  • MySQL 8.0 Reference Manual · JSON Aggregation Functions
  • PostgreSQL Documentation · Aggregate Functions · json_agg
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌