像大多数其他关系数据库产品一样,PostgreSQL支持聚合函数。聚合函数从多个输入行计算单个结果。例如,有一些聚合函数可以计算行集合上的count
(计数)、sum
(求和)、avg
(平均值)、max
(最大值)和min
(最小值)。
例如,我们可以找到任何地方的最高低温读数:
SELECT max(temp_lo) FROM weather;
max ----- 46 (1 row)
如果我们想知道这个读数是在哪个城市(或哪些城市)发生的,我们可以尝试
SELECT city FROM weather WHERE temp_lo = max(temp_lo); -- WRONG
但这将无法工作,因为聚合函数max
不能在WHERE
子句中使用。(存在此限制是因为WHERE
子句决定了哪些行将包含在聚合计算中;因此,它显然必须在计算聚合函数之前进行求值。)然而,像通常情况一样,查询可以重写以达到期望的结果,这里通过使用子查询
SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather);
city --------------- San Francisco (1 row)
这是可以的,因为子查询是一个独立的计算,它独立于外部查询中的操作来计算自己的聚合。
聚合函数与GROUP BY
子句结合使用也非常有用。例如,我们可以使用以下语句获取每个城市观测到的读数数量和最高低温度:
SELECT city, count(*), max(temp_lo) FROM weather GROUP BY city;
city | count | max ---------------+-------+----- Hayward | 1 | 37 San Francisco | 2 | 46 (2 rows)
这为每个城市提供了一行输出。每个聚合结果都是在与该城市匹配的表行上计算的。我们可以使用HAVING
来过滤这些分组行
SELECT city, count(*), max(temp_lo) FROM weather GROUP BY city HAVING max(temp_lo) < 40;
city | count | max ---------+-------+----- Hayward | 1 | 37 (1 row)
这为我们提供了仅对所有temp_lo
值低于40的城市的相同结果。最后,如果我们只关心名字以““S
””开头的城市,我们可以这样做:
SELECT city, count(*), max(temp_lo) FROM weather WHERE city LIKE 'S%' -- (1) GROUP BY city;
city | count | max ---------------+-------+----- San Francisco | 2 | 46 (1 row)
理解聚合函数和SQLWHERE
和HAVING
子句之间的交互很重要。 WHERE
和HAVING
之间的根本区别是:WHERE
在分组和聚合计算之前选择输入行(因此,它控制哪些行进入聚合计算),而HAVING
在分组和聚合计算之后选择组行。因此,WHERE
子句不得包含聚合函数;使用聚合函数来确定哪些行将成为聚合函数的输入是没有意义的。另一方面,HAVING
子句总是包含聚合函数。(严格来说,允许您编写不使用聚合函数的HAVING
子句,但这很少有用。相同的条件可以更有效地在WHERE
阶段使用。)
在前面的示例中,我们可以将城市名称限制应用于WHERE
,因为它不需要聚合。这比将限制添加到HAVING
更有效,因为我们避免了对所有不满足WHERE
检查的行执行分组和聚合计算。
选择将哪些行用于聚合计算的另一种方法是使用FILTER
,这是一个每个聚合函数的可选参数
SELECT city, count(*) FILTER (WHERE temp_lo < 45), max(temp_lo) FROM weather GROUP BY city;
city | count | max ---------------+-------+----- Hayward | 1 | 37 San Francisco | 1 | 46 (2 rows)
FILTER
meget 像 WHERE
,但它只从它所附加的特定聚合函数的输入中删除行。在这里,count
聚合函数只计算temp_lo
低于45的行;但max
聚合函数仍然应用于所有行,因此它仍然找到46的读数。
如果您在文档中看到任何不正确、与您对特定功能的使用经验不符或需要进一步澄清的内容,请使用此表单报告文档问题。