直接用 unnest() 在 select 列表中报错,因 postgresql 要求集合返回函数必须在 lateral 子查询或 from 项中执行,以明确行生成上下文;lateral 支持逐行展开并引用左侧行,而普通 select 无此语义。
为什么直接用 unnest() 在 SELECT 里会报错“set-returning function called in context that cannot accept a set”
因为 PostgreSQL 不允许在普通 SELECT 列表中直接调用返回多行的函数(如 unnest()),除非它被包裹在 LATERAL 子查询中,或作为独立的 FROM 项。常见错误是写成:
SELECT id, unnest(tags) FROM posts;
——这在 9.6+ 会失败。
根本原因是:SQL 标准要求集合返回函数必须有明确的“行生成上下文”,LATERAL 就是告诉优化器“这个函数依赖当前行,且每行可展开出 0–N 行”。
- 不加
LATERAL,PostgreSQL 无法确定unnest()的执行时机和关联粒度 -
LATERAL允许右侧子查询引用左侧的列,形成逐行展开语义 - 即使数组为空(
NULL或{}),LATERAL+unnest()默认跳过该行;需加LEFT JOIN才保留空数组行
如何用 LATERAL + unnest() 实现带聚合的数组展开(比如统计每个 tag 出现次数)
关键在于把 unnest() 放进 FROM 子句,并用 LATERAL 绑定到原表,再对展开后的结果做 GROUP BY。
例如统计所有文章中的标签频次: