2025年9月25日: PostgreSQL 18 釋出!
支援的版本:當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2

2.7. 聚合函式 #

像大多數其他關係資料庫產品一樣,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)

(1)

LIKE運算子執行模式匹配,並在第 9.7 節中進行解釋。

理解聚合函式和SQLWHEREHAVING子句之間的互動很重要。 WHEREHAVING之間的根本區別是: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的讀數。

提交更正

如果您在文件中看到任何不正確、與您對特定功能的使用經驗不符或需要進一步澄清的內容,請使用此表單報告文件問題。