跳至主要內容

2.7 聚合函数

LiuSongLing大约 3 分钟pgsqlpgsql

PostgreSQL 支持聚合函数。

聚合函数从多个输入行计算单个结果。

例如,有一些聚合用于计算一组行的 count(计数)、sum(总和)、avg(平均值)、max(最大值)和 min(最小值)。

例如,找到最高的低温读数:

SELECT max(temp_lo) FROM weather;

如果我们想知道最高的低温读数发生在哪个城市(或多个城市),我们可以尝试:

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);

这是可以的,因为 subquery(子查询) 是一个独立的计算,它与外部 query 中发生的情况分开计算自己的 聚合函数 max。





聚合与 GROUP BY 子句结合使用也非常有用。

例如,我们可以使用以下公式获取每个城市观测到的读数数量和最高低温:

SELECT city, count(*), max(temp_lo)
    FROM weather
    GROUP BY city;

我们可以使用 HAVING 过滤这些分组的行:

SELECT city, count(*), max(temp_lo)
    FROM weather
    GROUP BY city
    HAVING max(temp_lo) < 40;

如果我们只关心名称以 “S” 开头的城市,我们可能会这样做:

SELECT city, count(*), max(temp_lo)
    FROM weather
    WHERE city LIKE 'S%'            -- (1)
    GROUP BY city;





了解聚合与 SQL 的 WHERE 和 HAVING 子句之间的交互非常重要。

WHERE 和 HAVING 之间的根本区别在于: WHERE 在计算组和聚合之前选择 Importing 行(因此,它控制哪些行进入聚合计算),而 HAVING 在计算组和聚合之后选择组行。

因此,WHERE 子句不得包含聚合函数;

尝试使用 aggregate 来确定哪些行将成为 aggregates 的 Importing 是没有意义的。

另一方面,HAVING 子句始终包含聚合函数。(严格来说,你可以编写一个不使用聚合的 HAVING 子句,但它很少有用。在 WHERE 阶段可以更有效地使用相同的条件。




选择进入聚合计算的行的另一种方法是使用 FILTER,这是一个按聚合的选项:

SELECT city, count(*) FILTER (WHERE temp_lo < 45), max(temp_lo)
    FROM weather
    GROUP BY city;

FILTER 与 WHERE 非常相似,不同之处在于它仅从它所附加到的特定聚合函数的 Importing 中删除行。

在这里,count 计数聚合仅对 temp_lo 小于 45 的行进行计数;

但是 Max 聚合仍应用于所有行,因此它仍然会找到 46 的读数。