9.15. 聚集函數

聚集函數 從一套輸入值裡計算一個結果。 Table 9-37 顯示了內建聚集函數。 聚集函數的特殊語法在 Section 4.2.7裡解釋。請參考 Part I 獲取附加的介紹性訊息。

Table 9-37. 聚集函數

函數參數類型返回類型描述
avg(expression) 所有輸入值的均值(算術平均) smallint, integer, bigint, real, double precision, numeric, 或 interval. 對於任何整數類型輸入,結果都是 numeric 類型。 對於任何浮點輸入,結果都是 double precision 類型。 否則和輸入資料類型相同。 所有輸入值的平均(算術平均)。
bit_and(expression) smallint, integer, bigint, 或者 bit 和參數資料類型相同 所有非空輸入值的按位 AND (與),如果沒有,則為空
bit_or(expression) smallint, integer, bigint, 或者 bit 和參數資料類型相同 所有非空輸入值的按位 OR (或),如果沒有,則為空
bool_and(expression) bool bool 如果所有輸入值都是真,則為真,否則為假
bool_or(expression) bool bool 如果至少有一個輸入值為真,則為著,否則為假
count(*) bigint輸入值的個數
count(expression)任意bigint 計算那些 expression 非 NULL 的輸入的個數。
every(expression) bool bool 等效於 bool_and
max(expression)任何數值,字串或者日期/時間類型與參數同類型所有輸入值中, expression 的最大值
min(expression)任何數值,字串或者日期/時間類型與參數同類型所有輸入值中, expression 的最小值
stddev(expression) smallint, integer, bigint, real, double precision, 或 numeric. 浮點數參數時是double precision, 否則 numeric輸入值的標準採樣偏差(sample standard deviation)
sum(expression) smallint, integer, bigint, real, double precision, numeric, 或者 interval smallintinteger輸入 輸出類型為 bigint。對於bigint輸入輸出類型為 numeric, 浮點數輸入的結果是 double precision。 否則和輸入資料類型相同。 所有輸入值的 expression 的總和
variance(expression) smallint, integer, bigint, real, double precision, 或者 numeric. 浮點數參數是 double precision, 否則是 numeric輸出值的採樣方差(標準採樣偏差的平方)。

請注意除了 count 以外, 這些函數在沒有選中行時返回 NULL。 尤其要指出的是對零輸入行進行 sum 將返回 NULL, 而不是我們預期的零。 必要時可以用 coalesce 把 NULL 替換成零。

注意: 布爾聚集 bool_andbool_or 對應標準的 SQL 聚集 everyany 或者 some。對於 anysome, 標準語法裡面似乎有些內置的歧義:

SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...;

這裡的 ANY 既可以被認為是引出一個子查詢,也可以認為是一個聚集(如果查詢資料表達式返回 1 行電話)。 因此標準的名字無法用於這些聚集。

注意: 習慣了使用其它 RDBMS 產品的用戶可能會對 PostgreSQL 裡面的一些聚集函數的性能特點感到奇怪,特別是對整個資料表進行聚集的時候 (換句話說,不聲明 WHERE 子句的時候)。 比如,一個下面這樣的查詢:

SELECT min(col) from sometable;

將會被 PostgreSQL 以對整個資料表進行順序掃瞄的形式進行執行。 而其它資料庫系統可能會把這樣的查詢優化成使用某個字串上的索引的方式(如果有索引的話)。 在 PostgreSQL 裡類似的還有, 如果對整個資料表進行處理的話,聚集函數 max()count() 總是要求一次順序掃瞄。

PostgreSQL 無法很容易地實現這樣的 優化,因為它還允許用戶定義的聚集查詢。因為 min()max(),和 count() 都是使用一個聚集函數的普通 API 定義的,因此在某些場合裡, 這些函數的執行並不需要規定"特殊轉換"

幸運的是,對於 min()max(), 我們有些簡單的方法來繞開。比如下面顯示的查詢就等效於上面的查詢, 但是,如果在目標字串上有索引,那麼它可以利用一個 B+ 樹索引來優化。

SELECT col from sometable ORDER BY col ASC LIMIT 1;

類似的查詢(透過把上面查詢的 ASC 替換成 DESC 就行了)也可以用在 max() 的地方。

糟糕的是,在對全資料表操作的時候,沒有類似簡單的查詢可以用於改進 count() 的性能。