支援的版本:目前 (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 支援聚合函數。 聚合函數從多個輸入列計算單一結果。 例如,有聚合函數可以計算一組列的countsumavg (平均值)、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非常像WHERE,但它只從附加到的特定聚合函數的輸入中刪除列。 在這裡,count聚合僅計算temp_lo低於 45 的列;但max聚合仍然應用於所有列,因此它仍然找到 46 的讀數。

提交更正

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