array_agg必须配合group by,否则报错;排序需在函数内用order by;空组返回null,需coalesce兜底;array_agg返回数组类型,string_agg返回字符串,不可混用。

ARRAY_AGG 必须配合 GROUP BY,否则直接报错
不加 GROUP BY 却用 ARRAY_AGG,PostgreSQL 会报类似 ERROR: column "xxx" must appear in the GROUP BY clause or be used in an aggregate function 的错误。这不是配置问题,而是语义限制:数据库必须知道“把哪些行压进同一个数组”。
三种合法写法:
- 按业务字段分组:
SELECT dept, ARRAY_AGG(name) FROM employees GROUP BY dept - 多列组合分组:
SELECT dept, role, ARRAY_AGG(id) FROM employees GROUP BY dept, role - 全表聚合成单个数组(少见但有效):
SELECT ARRAY_AGG(name) FROM employees GROUP BY ()
ORDER BY 必须写在 ARRAY_AGG() 括号里,放外面无效
很多人写成 SELECT dept, ARRAY_AGG(name) FROM employees GROUP BY dept ORDER BY name,结果发现数组内元素顺序还是乱的——因为外层 ORDER BY 只控制最终结果集的行顺序,不改变数组结构。
真正生效的排序必须嵌在函数参数中:
- 升序(默认):
ARRAY_AGG(name ORDER BY name) - 降序且 NULL 排最后:
ARRAY_AGG(name ORDER BY name DESC NULLS LAST) - 按表达式排序(如长度):
ARRAY_AGG(name ORDER BY LENGTH(name), name)
不写 ORDER BY 时,顺序由扫描路径决定,不可依赖;生产环境务必显式声明。
空分组返回 NULL,不是 {},应用层容易崩
当某组无匹配行(比如 WHERE status = 'active' 但该部门下没人 active),ARRAY_AGG(col) 直接返回 NULL,不是空数组 {}。Python、Django 或前端解析时容易触发 NoneType 错误。
稳妥兜底方式:
-
COALESCE(ARRAY_AGG(col), ARRAY[]::text[])—— 显式类型声明,最安全 -
COALESCE(ARRAY_AGG(col) FILTER (WHERE col IS NOT NULL), ARRAY[]::text[])—— 同时过滤 NULL 值并兜底空组
别用 ARRAY_AGG(COALESCE(col, '')):这只是把 NULL 转成空字符串,解决不了整组为空的问题。
ARRAY_AGG 和 STRING_AGG 不是替代关系,选错类型后续很难补救
ARRAY_AGG 返回的是 SQL 数组类型(如 text[]、integer[]),能直接被 UNNEST、arr[1]、array_length 等原生函数处理;STRING_AGG 返回字符串,再想拆分就得靠 string_to_array(),多一次解析、易出错、丢失原始类型。
典型误用场景:
- 需要后续对聚合结果求和(如
sum(arr))?必须用ARRAY_AGG - 只是导出 CSV 或前端展示?
STRING_AGG(col, ', ')更轻量 - 想把
ARRAY_AGG结果转字符串?用ARRAY_TO_STRING(ARRAY_AGG(col), ', '),但注意类型匹配(integer[]需先转text[])
嵌套聚合(如二维数组)不能直接写 ARRAY_AGG(ARRAY_AGG(...)),会报 cannot aggregate arrays;必须用子查询或 CTE 拆解。










