在PostgreSQL的日常开发场景中,经常会遇到需要将多行聚合数据转换为JSON数组的需求,比如接口返回用户对应的多个订单信息、统计分组下的多个标签数据等,JSON_AGG函数就是专门解决这类问题的内置聚合函数,能够直接将分组后的行数据聚合为JSON数组格式。

JSON_AGG函数基本语法
JSON_AGG函数的作用是将一组值聚合为一个JSON数组,基本语法格式如下:
JSON_AGG ( expression [ ORDER BY sort_expression ] )
其中expression是要聚合的表达式,可以是表的列名、行记录或者计算后的表达式;ORDER BY是可选参数,用于指定聚合后JSON数组中元素的排序规则,如果不指定则元素的顺序不固定。
单表聚合结果转JSON数组示例
假设我们有一个用户标签表user_tags,表结构如下:
CREATE TABLE user_tags (
user_id INT,
tag_name VARCHAR(50),
create_time TIMESTAMP
);
现在需要查询每个用户对应的所有标签,并且将标签聚合为JSON数组,SQL语句如下:
SELECT
user_id,
JSON_AGG(tag_name ORDER BY create_time DESC) AS tag_list
FROM user_tags
GROUP BY user_id;
执行后,每个用户对应的tag_list字段就是按创建时间倒序排列的标签JSON数组,比如用户1的结果可能是["标签3", "标签1", "标签2"]。
多表关联聚合结果转JSON数组示例
如果有用户表users和用户订单表orders,需要查询每个用户的基本信息以及对应的所有订单信息,将订单聚合为JSON数组,表结构如下:
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50)
);
-- 订单表
CREATE TABLE orders (
id INT PRIMARY KEY,
user_id INT,
order_no VARCHAR(50),
amount DECIMAL(10,2)
);
可以使用JSON_AGG聚合订单行记录,SQL语句如下:
SELECT
u.id,
u.username,
JSON_AGG(
json_build_object(
'order_id', o.id,
'order_no', o.order_no,
'amount', o.amount
) ORDER BY o.id
) AS order_list
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.username;
这里使用json_build_object函数先构建每个订单的JSON对象,再通过JSON_AGG聚合为数组,最终order_list字段就是包含多个订单对象信息的JSON数组。
使用注意事项
- 如果聚合的分组中没有匹配的行,JSON_AGG函数会返回
[]空数组,而不是NULL,这一点在使用LEFT JOIN等场景时需要注意。 - 如果需要聚合为JSON对象而不是数组,可以使用
JSON_OBJECT_AGG函数,它可以将键值对聚合为JSON对象。 - 当聚合的表达式包含NULL值时,JSON_AGG会将NULL值直接放入JSON数组中,如果需要过滤NULL值,可以在聚合前使用WHERE条件或者
FILTER子句。
常见问题解决
如果遇到聚合后的JSON数组顺序不符合预期的问题,检查是否添加了ORDER BY子句,JSON_AGG默认不保证元素顺序,必须显式指定排序规则。
如果需要将聚合结果转为其他格式,比如只聚合某一列的非重复值,可以结合DISTINCT使用,示例如下:
SELECT
user_id,
JSON_AGG(DISTINCT tag_name) AS unique_tag_list
FROM user_tags
GROUP BY user_id;
上述语句会先对tag_name去重,再聚合为JSON数组,避免重复标签出现。
PostgreSQLJSON_AGGJSON数组聚合函数修改时间:2026-06-21 15:09:16