PostgreSQL HAVING和WHERE子句区别详解

我们在写SQL时常常会使用where和having子句来进行数据的过滤。但是这两者具体区别在哪呢?
PostgreSQL中和其它关系型数据库一样也支持聚合函数,一个聚合函数是指从多个输入行中计算出一个结果。
而对于where和having子句最大的区别在于:Where中不能使用聚合函数,而having中可以使用聚合函数。
那么为什么会有这种限制呢?我们来看个例子:

–找出所有记录中id最大的记录:

bill@bill=>select max(id) from t1;
 max 
-----
  99
(1 row)

接下来我们想要知道最大id的记录对应的name是哪个用户,我们可以用:

bill@bill=>select name from t1 where id=max(id);

但实际执行时就会发现会报错:

ERROR:  aggregate functions are not allowed in WHERE

因为聚合函数max不能被用于WHERE子句中,存在这个限制是因为:WHERE子句决定哪些行可以被聚合计算包括;因此显然它必需在聚合函数之前被计算。

为了实现上述的目的,我们可以运用子查询:

bill@bill=>SELECT name FROM t1
bill-# WHERE id = (SELECT max(id) FROM t1);
  name  
--------
 foucus
(1 row)

这样做是 OK 的,因为子查询是一次独立的计算,它独立于外层的查询计算出自己的聚合。

聚合同样也常用于和GROUP BY子句组合。比如,我们可以获取每个用户的最大id值:

bill@bill=>SELECT name, max(id) FROM t1  GROUP BY name;
  name  | max 
--------+-----
 bill   |  96
 foucus |  99
(2 rows)

这样我们给每个用户一个输出。每个聚合结果都是在匹配该用户的表行上面计算的。我们可以用HAVING来过滤这些被分组的行:

bill@bill=>SELECT name, max(id)
FROM t1
GROUP BY name
HAVING max(id) < 100;
  name  | max 
--------+-----
 bill   |  96
 foucus |  99
(2 rows)

总结:
WHERE和HAVING的基本区别如下:
WHERE在分组和聚集计算之前选取输入行(因此,它控制哪些行进入聚集计算),而HAVING在分组和聚集之后选取分组行。

因此,WHERE子句不能包含聚合函数; 因为试图用聚合函数判断哪些行应输入给聚合运算是没有意义的。相反,HAVING子句总是包含聚合函数(严格说来,你可以写不使用聚合的HAVING子句, 但这样做很少有用。 同样的条件用在WHERE阶段会更有效)。

参考链接:
https://www.postgresql.org/docs/12/tutorial-agg.html

发布了155 篇原创文章 · 获赞 88 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_39540651/article/details/105193257