是,默认会将NULL值纳入数组,如[1, NULL, 3];需用FILTER(WHERE col IS NOT NULL)显式过滤或COALESCE处理,否则易导致UNNEST或JSON转换异常。

ARRAY_AGG 会把 NULL 值也塞进数组里
默认行为下,ARRAY_AGG 不会过滤 NULL,只要某行对应字段是 NULL,结果数组里就多一个 NULL 元素。这常导致后续 UNNEST 或应用层解析出错。
解决办法是加 FILTER 子句或用 WHERE 预过滤:
SELECT ARRAY_AGG(name FILTER (WHERE name IS NOT NULL)) FROM users;
或者更干脆地:
SELECT ARRAY_AGG(name) FROM users WHERE name IS NOT NULL;
注意二者语义不同:前者对整组计算但只聚合非空值;后者先排除空行再聚合——如果分组内全为 NULL,FILTER 版返回空数组 {},WHERE 版返回 NULL。
排序不稳定会导致每次查询结果顺序不一致
ARRAY_AGG 本身不保证顺序,尤其在并行查询或数据有变动时,同一语句多次执行可能得到不同排列的数组。
必须显式用 ORDER BY 子句控制顺序:
SELECT ARRAY_AGG(name ORDER BY created_at DESC) FROM users GROUP BY category;
常见疏漏点:
- 忘了写
ORDER BY,靠直觉认为“插入顺序就是返回顺序”——PostgreSQL 不承诺这个 - 在
GROUP BY场景中,ORDER BY表达式必须能被分组键函数依赖,否则报错column "xxx" must appear in the GROUP BY clause - 想按别名排序(如
ORDER BY updated_at DESC AS last_time)不行,得写原始列或表达式
聚合字符串时容易忽略类型不匹配报错
如果字段是 TEXT、VARCHAR 混用,或含 JSONB 字段,ARRAY_AGG 可能因隐式类型转换失败而报错:
ERROR: could not determine polymorphic type because input has type "unknown"
典型触发场景:
- 对字面量直接聚合:
ARRAY_AGG('hello')→ 改成ARRAY_AGG('hello'::TEXT) - 联合查询中某列类型模糊:
SELECT ARRAY_AGG(COALESCE(a.name, b.title))...→ 显式转类型:COALESCE(a.name, b.title)::TEXT - 聚合
JSONB字段却没声明类型:ARRAY_AGG(data)→ 写成ARRAY_AGG(data::JSONB)
类型推导失败时,PostgreSQL 不会自动兜底,必须人工锚定。
大数据量下 ARRAY_AGG 可能触发内存溢出或超时
当单个分组聚合几万甚至几十万个元素时,ARRAY_AGG 会一次性加载全部值到内存构造数组,容易触发 out of memory 或被 statement_timeout 中断。
应对策略不是“调大内存”,而是从设计上规避:
- 确认业务是否真需要完整数组——有时前端只需要前 10 个,可用
LIMIT配合子查询提前截断 - 用
STRING_AGG替代(如果最终只用于拼接展示),它流式处理、内存友好得多 - 分页聚合:先用
ROW_NUMBER() OVER (PARTITION BY ...)标序号,再外层按序号分段聚合
数组长度没有硬性上限,但实际受 work_mem 和单行大小限制(PostgreSQL 单行最大约 1.6TB,但现实里几百 MB 就已危险)。

















