array_agg是PostgreSQL中将分组后多行标量值聚合成数组的标准聚合函数,支持ORDER BY和FILTER WHERE过滤NULL,但默认保留NULL且不保序。

ARRAY_AGG 能把分组后的多行值聚合成一个数组,但默认行为容易导致空值、排序混乱或类型不一致——直接用可能查出意外结果。
ARRAY_AGG 会把 NULL 值也塞进数组里
如果某列存在 NULL,ARRAY_AGG(col) 默认保留它,生成类似 {1, NULL, 3} 的数组,后续用 UNNEST 或下标访问时容易报错或跳过逻辑。
- 加
FILTER (WHERE col IS NOT NULL)显式过滤(PostgreSQL 9.4+) - 或用
ARRAY_AGG(col) FILTER (WHERE col '')排除空字符串(若字段是文本) - MySQL 没原生
ARRAY_AGG,得用JSON_ARRAYAGG(),它默认忽略NULL,这点反而更安全
不指定 ORDER BY 时,数组元素顺序不确定
SQL 标准不保证未排序聚合的顺序,即使当前执行看起来有序,换数据量或优化器路径就可能变。
- 必须写成
ARRAY_AGG(col ORDER BY sort_col)(PostgreSQL) - BigQuery 语法稍不同:用
ARRAY_AGG(col ORDER BY sort_col),支持LIMIT截断 - ClickHouse 用
groupArray(col),要排序得套一层arraySort(),不能在聚合里直接写ORDER BY
跨数据库类型兼容性差,别硬套同一写法
ARRAY_AGG 不是所有 SQL 引擎都支持,且返回类型不同:PostgreSQL 返回 text[] 或具体类型数组,BigQuery 返回 ARRAY<T>,而 SQLite 根本没有这个函数。
- PostgreSQL 示例:
SELECT user_id, ARRAY_AGG(tag ORDER BY created_at) AS tags FROM user_tags GROUP BY user_id - BigQuery 替代:
SELECT user_id, ARRAY_AGG(tag ORDER BY created_at) AS tags FROM user_tags GROUP BY user_id(语法像,但类型系统更严格) - SQLite 只能拼字符串:
GROUP_CONCAT(tag, ','),再在应用层解析——这不是数组,只是逗号分隔文本
最常被忽略的是:聚合后数组长度没做校验。比如用 tags[1] 取首元素,但数组可能是空的,PostgreSQL 会返回 NULL,而某些 ORM 会直接抛异常。上线前得确认下游是否容忍空数组或越界访问。

















