與大多數其他關聯式資料庫產品一樣,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)
理解聚合和SQL的WHERE
和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
非常像WHERE
,但它只從附加到的特定聚合函數的輸入中刪除列。 在這裡,count
聚合僅計算temp_lo
低於 45 的列;但max
聚合仍然應用於所有列,因此它仍然找到 46 的讀數。
如果您在文件中發現任何不正確、與特定功能的體驗不符或需要進一步澄清的內容,請使用此表格來報告文件問題。