ARRAY_AGG()需配合GROUP BY使用、默认保留NULL、ORDER BY须写在函数内;空组返回NULL需COALESCE补空;类型不匹配时须显式转换;越界访问可能引发应用崩溃。

直接用 ARRAY_AGG() 就行,但必须明确三点:它只在 GROUP BY 场景下有意义、默认保留 NULL、不写 ORDER BY 就不保序。
为什么 GROUP BY 是硬性前提?
PostgreSQL 15 不允许在没 GROUP BY 的情况下混用聚合函数和普通列。比如 SELECT id, ARRAY_AGG(name) 会报错 column "id" must appear in the GROUP BY clause。只有两种合法写法:
-
SELECT ARRAY_AGG(name) FROM users(全表聚合,结果只有一行) -
SELECT dept, ARRAY_AGG(name) FROM users GROUP BY dept(按部门分组,每组一个数组)
NULL 值怎么处理才不踩坑?
ARRAY_AGG() 默认把 NULL 当成有效元素塞进数组,比如 {'Alice', NULL, 'Bob'}。后续用 UNNEST 或下标访问时容易出错。稳妥做法是显式过滤:
- 用
FILTER (WHERE name IS NOT NULL):更清晰,推荐 - 或提前在子查询里
WHERE name IS NOT NULL再聚合 - 空组(如某部门没人)返回的是
NULL,不是空数组{};需用COALESCE(ARRAY_AGG(name), ARRAY[]::text[])补空
ORDER BY 必须写在函数内部,不能外挂
数组内元素顺序由 ARRAY_AGG(name ORDER BY created_at DESC) 控制,不是 ARRAY_AGG(name) ORDER BY created_at DESC——后者语法错误,且只影响最终结果集排序,不影响数组内容。
- 支持多字段排序:
ARRAY_AGG(id ORDER BY status, updated_at DESC) - 不加
ORDER BY时,顺序取决于执行计划,可能每次查询都不同 - 若字段类型不支持排序(如
jsonb),得先转成可比类型,例如ARRAY_AGG(data->>'name' ORDER BY data->>'name')
聚合后想转字符串?别套 STRING_AGG,用 ARRAY_TO_STRING
STRING_AGG() 和 ARRAY_AGG() 是并列函数,不是上下游关系。真要字符串拼接,优先选 STRING_AGG(name, ', ');如果已用了 ARRAY_AGG,再转就用:
-
ARRAY_TO_STRING(ARRAY_AGG(name), ', ', '*')(第三参数是NULL替代符) - 注意类型匹配:
ARRAY_AGG(id)返回integer[],传给ARRAY_TO_STRING前得显式转text[],例如ARRAY_TO_STRING(ARRAY_AGG(id)::text[], ', ') - 性能上,
STRING_AGG比ARRAY_AGG + ARRAY_TO_STRING略快,尤其大数据量时
最常被忽略的是数组越界访问——比如用 tags[1] 取首元素,但数组可能是空的或长度为 0,PostgreSQL 返回 NULL,而某些应用层代码会直接崩溃。上线前务必检查下游是否能容忍空数组或下标越界。

















