是,array_agg 默认保留 null 作为数组元素;不加 where 或 filter 会导致 [null, 'a', null] 类结果,易引发 unnest 或 json 转换异常。

ARRAY_AGG 会把 NULL 值也塞进数组里吗?
会,ARRAY_AGG 默认保留 NULL,生成的数组里可能出现 NULL 元素。这在后续用 UNNEST 或 JSON 转换时容易引发意外行为。
实操建议:
PostgreSQL 18.4 官方 Ubuntu 安装包现已发布,这是目前最新的稳定版本。推荐通过官方 APT 仓库安装:先执行 sudo apt update 更新索引,再运行 sudo apt install postgresql-18 即可完成部署。新版本引入了异步 I/O 子系统,在顺序扫描与 VACUUM 场景下性能提升显著,同时支持 UUID v7 原生生成函数与虚拟生成列。
- 加
WHERE column_name IS NOT NULL过滤掉空值(推荐,语义清晰) - 或用
ARRAY_AGG(column_name) FILTER (WHERE column_name IS NOT NULL)(PostgreSQL 9.4+ 支持,更灵活) - 避免依赖
COALESCE包裹字段——它只是替换值,不改变行存在性,对去 NULL 无效
ORDER BY 能不能用在 ARRAY_AGG 里面?
能,而且强烈建议显式指定。不加 ORDER BY 时,ARRAY_AGG 返回顺序是不确定的(取决于扫描顺序和并行计划),同一查询多次执行可能得到不同数组。
实操建议:
- 写成
ARRAY_AGG(column_name ORDER BY column_name)(支持单列或多列,语法紧凑) - 若需倒序,直接写
ORDER BY column_name DESC - 注意:不能在外部
GROUP BY查询的ORDER BY子句里控制ARRAY_AGG内部顺序——那是作用于最终结果集的
聚合字符串时,用 STRING_AGG 还是 ARRAY_AGG + array_to_string?
优先用 STRING_AGG。虽然 ARRAY_AGG 配合 array_to_string 也能拼接,但多了一层类型转换开销,且无法原生处理分隔符 NULL 处理逻辑(比如跳过空值)。
实操建议:
- 纯字符串拼接场景,直接上
STRING_AGG(name, ', ' ORDER BY name) - 需要后续再拆解、去重、索引访问或转 JSON,则选
ARRAY_AGG——数组是结构化容器,字符串是扁平文本 -
STRING_AGG的ON OVERFLOW TRUNCATE(PG 16+)对长文本更可控;ARRAY_AGG溢出会直接报错
GROUP BY 字段含中文或特殊字符,ARRAY_AGG 结果乱码或报错?
不是 ARRAY_AGG 的问题,而是客户端编码或数据库服务端 client_encoding 不一致导致的显示异常。数组本身是二进制安全的,存储无损。
实操建议:
- 检查连接时的编码:
SHOW client_encoding;应为UTF8 - 若用 psql,启动时加
-c 'SET client_encoding = UTF8'或配置.psqlrc - 应用层(如 Python psycopg2)确保连接参数含
client_encoding='utf8' - 别在
ARRAY_AGG外层套CONVERT_FROM或ENCODE——徒增错误风险
ARRAY_AGG(DISTINCT user_id ORDER BY user_id) FILTER (WHERE status = 'active')。这种写法看着长,但每部分都对应一个明确意图,比事后在应用层处理更可靠。










