为何PostgreSQL中一个聚合查询正常执行,另一个却报错?
PostgreSQL中两个含聚合函数的HAVING子查询为何一个合法一个报错?
我在PostgreSQL测试套件中发现了一个奇怪的现象:
-- 测试外层聚合 -- 此查询应正常执行 select ten, sum(distinct four) from onek a group by ten having exists (select 1 from onek b where sum(distinct a.four) = b.four); -- 此查询应失败,因为子查询的WHERE子句中包含自身的聚合函数 select ten, sum(distinct four) from onek a group by ten having exists (select 1 from onek b where sum(distinct a.four + b.four) = b.four);
第二个查询报错:ERROR: aggregate functions are not allowed in WHERE。但第一个查询的WHERE子句里也出现了聚合函数,两者唯一区别是sum函数的传入值,为何第一个合法,第二个却报错?
核心原因:聚合函数的计算范围不同
第一个查询的聚合属于外层分组结果:
外层查询先对onek a按ten分组,计算出每组的sum(distinct a.four)值。当执行子查询时,这个值已经是确定的分组常量,子查询的WHERE子句只是用这个常量和b.four做等值对比,并没有在子查询内部执行聚合操作,完全符合SQL语法规则。第二个查询的聚合属于子查询自身:
这里的sum(distinct a.four + b.four)引用了子查询表b的列b.four,PostgreSQL会判定这个聚合需要在子查询的行范围内计算。而SQL语法明确规定,聚合函数不能直接出现在WHERE子句中(WHERE负责筛选原始行,聚合是基于行组的计算,逻辑上要先筛选行再做聚合,因此聚合应放在HAVING或SELECT子句中),所以触发了报错。
内容的提问来源于stack exchange,提问作者Mason Wheeler
相关产品推荐
相关产品推荐

