像大多数其他关系数据库产品一样,PostgreSQL 支持聚集函数。聚集函数从多行输入计算单个结果。例如,有聚集函数来计算计数
、求和
、平均值
、最大值
和最小值
。
例如,我们可以找到任何地方的最高低温值。
SELECT max(temp_lo) FROM weather;
max ----- 46 (1 row)
如果我们想知道该值出现在哪个城市(或哪些城市),我们可以尝试
SELECT city FROM weather WHERE temp_lo = max(temp_lo); WRONG
但是这行不通,因为聚集函数最大值
不能用于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)
理解聚集函数与WHERE
和HAVING
子句之间的交互非常重要。SQLWHERE
和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
类似于WHERE
,只不过它仅从特定聚集函数的输入中删除行。在这里,count
聚集仅计算temp_lo
低于 45 的行;但是max
聚集仍然应用于所有行,因此它仍然找到 46 的读取值。
如果您在文档中看到任何不正确、与您在特定功能上的经验不符或需要进一步澄清的内容,请使用 此表单 报告文档问题。