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 / 7.1

9.21. 聚合函式 #

聚合函式從一組輸入值計算單個結果。內建的通用聚合函式列在表 9.62中,而統計聚合函式列在表 9.63中。內建的組內有序集聚合函式列在表 9.64中,而內建的組內假設集(hypothetical-set)聚合函式列在表 9.65中。與聚合函式密切相關的分組操作列在表 9.66中。聚合函式的特殊語法注意事項在第 4.2.7 節中進行了說明。有關附加的介紹性資訊,請參閱第 2.7 節

支援部分模式(Partial Mode)的聚合函式有資格參與各種最佳化,例如並行聚合。

雖然所有下面的聚合函式都接受一個可選的 ORDER BY 子句(如第 4.2.7 節中所述),但該子句僅新增到輸出受排序影響的聚合函式中。

表 9.62. 通用聚合函式

函式

描述

部分模式

any_value ( anyelement ) → 與輸入型別相同

返回非空輸入值中的任意一個值。

array_agg ( anynonarray ORDER BY input_sort_columns ) → anyarray

將所有輸入值(包括 NULL)收集到一個數組中。

array_agg ( anyarray ORDER BY input_sort_columns ) → anyarray

將所有輸入陣列連線成一個維度更高的陣列。(輸入必須具有相同的維度,並且不能是空或 NULL。)

avg ( smallint ) → numeric

avg ( integer ) → numeric

avg ( bigint ) → numeric

avg ( numeric ) → numeric

avg ( real ) → double precision

avg ( double precision ) → double precision

avg ( interval ) → interval

計算所有非 NULL 輸入值的平均值(算術平均值)。

bit_and ( smallint ) → smallint

bit_and ( integer ) → integer

bit_and ( bigint ) → bigint

bit_and ( bit ) → bit

計算所有非 NULL 輸入值的按位 AND。

bit_or ( smallint ) → smallint

bit_or ( integer ) → integer

bit_or ( bigint ) → bigint

bit_or ( bit ) → bit

計算所有非 NULL 輸入值的按位 OR。

bit_xor ( smallint ) → smallint

bit_xor ( integer ) → integer

bit_xor ( bigint ) → bigint

bit_xor ( bit ) → bit

計算所有非 NULL 輸入值的按位異或(XOR)。可用於無序值集的校驗和。

bool_and ( boolean ) → boolean

如果所有非 NULL 輸入值都為 true,則返回 true,否則返回 false。

bool_or ( boolean ) → boolean

如果任何非 NULL 輸入值為 true,則返回 true,否則返回 false。

count ( * ) → bigint

計算輸入行的數量。

count ( "any" ) → bigint

計算輸入值非 NULL 的輸入行的數量。

every ( boolean ) → boolean

這是 SQL 標準中與 bool_and 等效的函式。

json_agg ( anyelement ORDER BY input_sort_columns ) → json

jsonb_agg ( anyelement ORDER BY input_sort_columns ) → jsonb

將所有輸入值(包括 NULL)收集到一個 JSON 陣列中。值將按照 to_jsonto_jsonb 進行 JSON 轉換。

json_agg_strict ( anyelement ) → json

jsonb_agg_strict ( anyelement ) → jsonb

將所有輸入值(跳過 NULL)收集到一個 JSON 陣列中。值將按照 to_jsonto_jsonb 進行 JSON 轉換。

json_arrayagg ( [ value_expression ] [ ORDER BY sort_expression ] [ { NULL | ABSENT } ON NULL ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ])

其行為與 json_array 相同,但作為聚合函式,它只有一個 value_expression 引數。如果指定了 ABSENT ON NULL,則會忽略 NULL 值。如果指定了 ORDER BY,則元素將按照該順序出現在陣列中,而不是按照輸入順序。

SELECT json_arrayagg(v) FROM (VALUES(2),(1)) t(v)[2, 1]

json_objectagg ( [ { key_expression { VALUE | ':' } value_expression } ] [ { NULL | ABSENT } ON NULL ] [ { WITH | WITHOUT } UNIQUE [ KEYS ] ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ])

其行為與 json_object 相同,但作為聚合函式,它只有一個 key_expression 和一個 value_expression 引數。

SELECT json_objectagg(k:v) FROM (VALUES ('a'::text,current_date),('b',current_date + 1)) AS t(k,v){ "a" : "2022-05-10", "b" : "2022-05-11" }

json_object_agg ( key "any", value "any" ORDER BY input_sort_columns ) → json

jsonb_object_agg ( key "any", value "any" ORDER BY input_sort_columns ) → jsonb

將所有鍵/值對收集到一個 JSON 物件中。鍵引數被強制轉換為文字;值引數按照 to_jsonto_jsonb 進行轉換。值可以是 NULL,但鍵不能是 NULL。

json_object_agg_strict ( key "any", value "any" ) → json

jsonb_object_agg_strict ( key "any", value "any" ) → jsonb

將所有鍵/值對收集到一個 JSON 物件中。鍵引數被強制轉換為文字;值引數按照 to_jsonto_jsonb 進行轉換。鍵引數不能為 NULL。如果值是 NULL,則跳過該條目。

json_object_agg_unique ( key "any", value "any" ) → json

jsonb_object_agg_unique ( key "any", value "any" ) → jsonb

將所有鍵/值對收集到一個 JSON 物件中。鍵引數被強制轉換為文字;值引數按照 to_jsonto_jsonb 進行轉換。值可以是 NULL,但鍵不能是 NULL。如果存在重複鍵,則會丟擲錯誤。

json_object_agg_unique_strict ( key "any", value "any" ) → json

jsonb_object_agg_unique_strict ( key "any", value "any" ) → jsonb

將所有鍵/值對收集到一個 JSON 物件中。鍵引數被強制轉換為文字;值引數按照 to_jsonto_jsonb 進行轉換。鍵引數不能為 NULL。如果值是 NULL,則跳過該條目。如果存在重複鍵,則會丟擲錯誤。

max ( 參見文字 ) → 與輸入型別相同

計算非 NULL 輸入值的最大值。適用於任何數值、字串、日期/時間或列舉型別,以及 byteainetintervalmoneyoidpg_lsntidxid8,以及包含可排序資料型別的陣列和複合型別。

min ( 參見文字 ) → 與輸入型別相同

計算非 NULL 輸入值的最小值。適用於任何數值、字串、日期/時間或列舉型別,以及 byteainetintervalmoneyoidpg_lsntidxid8,以及包含可排序資料型別的陣列和複合型別。

range_agg ( value anyrange ) → anymultirange

range_agg ( value anymultirange ) → anymultirange

計算非 NULL 輸入值的並集。

range_intersect_agg ( value anyrange ) → anyrange

range_intersect_agg ( value anymultirange ) → anymultirange

計算非 NULL 輸入值的交集。

string_agg ( value text, delimiter text ) → text

string_agg ( value bytea, delimiter bytea ORDER BY input_sort_columns ) → bytea

將非 NULL 輸入值連線成一個字串。第一個值之後的每個值都前面帶有相應的 delimiter(如果它不是 NULL)。

sum ( smallint ) → bigint

sum ( integer ) → bigint

sum ( bigint ) → numeric

sum ( numeric ) → numeric

sum ( real ) → real

sum ( double precision ) → double precision

sum ( interval ) → interval

sum ( money ) → money

計算非 NULL 輸入值的總和。

xmlagg ( xml ORDER BY input_sort_columns ) → xml

將非 NULL XML 輸入值連線起來(參見第 9.15.1.8 節)。


需要注意的是,除了 count 之外,這些函式在沒有選擇行時會返回 NULL。特別是,沒有行的 sum 返回 NULL,而不是預期的零,而 array_agg 在沒有輸入行時返回 NULL 而不是空陣列。如有必要,可以使用 coalesce 函式將 NULL 替換為零或空陣列。

聚合函式 array_aggjson_aggjsonb_aggjson_agg_strictjsonb_agg_strictjson_object_aggjsonb_object_aggjson_object_agg_strictjsonb_object_agg_strictjson_object_agg_uniquejsonb_object_agg_uniquejson_object_agg_unique_strictjsonb_object_agg_unique_strictstring_aggxmlagg,以及類似的自定義聚合函式,其產生有意義的結果值取決於輸入值的順序。預設情況下,此排序是不確定的,但可以透過在聚合呼叫中編寫 ORDER BY 子句來控制,如第 4.2.7 節所示。或者,通常提供來自排序子查詢的輸入值可以奏效。例如:

SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab;

請注意,如果外部查詢級別包含其他處理(例如 JOIN),此方法可能會失敗,因為這可能導致子查詢的輸出在計算聚合之前被重新排序。

注意

布林聚合函式 bool_andbool_or 分別對應於標準 SQL 聚合函式 everyanysomePostgreSQL 支援 every,但不支援 anysome,因為標準語法中存在固有的歧義。

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

在這裡,ANY 可以被看作是引入子查詢,或者是一個聚合函式,如果子查詢返回一行布林值。因此,不能為這些聚合函式提供標準名稱。

注意

對於習慣於使用其他 SQL 資料庫管理系統的使用者來說,當 count 聚合應用於整個表時,其效能可能會令人失望。類似這樣的查詢:

SELECT count(*) FROM sometable;

將需要與表大小成比例的開銷:PostgreSQL 需要掃描整個表或包含表中所有行的索引的全部內容。

表 9.63 顯示了通常用於統計分析的聚合函式。(這些只是為了避免將更常用的聚合函式列表弄得過於擁擠而分開列出。)描述中提到接受 numeric_type 的函式適用於所有型別 smallintintegerbigintnumericrealdouble precision。在描述中提到 N 時,表示輸入行為非 NULL 的輸入行數。在所有情況下,如果計算無意義(例如 N 為零),則返回 NULL。

表 9.63. 統計聚合函式

函式

描述

部分模式

corr ( Y double precision, X double precision ) → double precision

計算相關係數。

covar_pop ( Y double precision, X double precision ) → double precision

計算總體協方差。

covar_samp ( Y double precision, X double precision ) → double precision

計算樣本協方差。

regr_avgx ( Y double precision, X double precision ) → double precision

計算自變數的平均值,即 sum(X)/N

regr_avgy ( Y double precision, X double precision ) → double precision

計算因變數的平均值,即 sum(Y)/N

regr_count ( Y double precision, X double precision ) → bigint

計算兩個輸入值都非 NULL 的行的數量。

regr_intercept ( Y double precision, X double precision ) → double precision

計算由 (X, Y) 對確定的最小二乘擬合線性方程的 y 截距。

regr_r2 ( Y double precision, X double precision ) → double precision

計算相關係數的平方。

regr_slope ( Y double precision, X double precision ) → double precision

計算由 (X, Y) 對確定的最小二乘擬合線性方程的斜率。

regr_sxx ( Y double precision, X double precision ) → double precision

計算自變數的“平方和”,即 sum(X^2) - sum(X)^2/N

regr_sxy ( Y double precision, X double precision ) → double precision

計算獨立變數與因變數的“乘積和”,即 sum(X*Y) - sum(X) * sum(Y)/N

regr_syy ( Y double precision, X double precision ) → double precision

計算因變數的“平方和”,即 sum(Y^2) - sum(Y)^2/N

stddev ( numeric_type ) → double precision for real or double precision, otherwise numeric

這是 stddev_samp 的歷史別名。

stddev_pop ( numeric_type ) → double precision for real or double precision, otherwise numeric

計算輸入值的總體標準差。

stddev_samp ( numeric_type ) → double precision for real or double precision, otherwise numeric

計算輸入值的樣本標準差。

variance ( numeric_type ) → double precision for real or double precision, otherwise numeric

這是 var_samp 的歷史別名。

var_pop ( numeric_type ) → double precision for real or double precision, otherwise numeric

計算輸入值的總體方差(總體標準差的平方)。

var_samp ( numeric_type ) → double precision for real or double precision, otherwise numeric

計算輸入值的樣本方差(樣本標準差的平方)。


列在表 9.64中的一些聚合函式使用了有序集聚合語法。這些函式有時被稱為逆分佈函式。它們的聚合輸入由 ORDER BY 引入,並且它們還可以接受一個不被聚合但只計算一次的直接引數。所有這些函式都會忽略其聚合輸入中的 NULL 值。對於那些接受 fraction 引數的函式,該分數值必須在 0 到 1 之間;否則會丟擲錯誤。但是,NULL fraction 值只會產生 NULL 結果。

表 9.64. 有序集聚合函式

函式

描述

部分模式

mode () WITHIN GROUP ( ORDER BY anyelement ) → anyelement

計算眾數,即聚合引數中最頻繁出現的值(如果有多個值出現頻率相同,則任意選擇第一個)。聚合引數必須是可排序的型別。

percentile_cont ( fraction double precision ) WITHIN GROUP ( ORDER BY double precision ) → double precision

percentile_cont ( fraction double precision ) WITHIN GROUP ( ORDER BY interval ) → interval

計算連續分位數,即對應於有序集聚合引數值中指定 fraction 的值。這將在需要時插入相鄰的輸入項。

percentile_cont ( fractions double precision[] ) WITHIN GROUP ( ORDER BY double precision ) → double precision[]

percentile_cont ( fractions double precision[] ) WITHIN GROUP ( ORDER BY interval ) → interval[]

計算多個連續分位數。結果是一個與 fractions 引數相同維度的陣列,每個非 NULL 元素都替換為對應於該分位數的值(可能經過插值)。

percentile_disc ( fraction double precision ) WITHIN GROUP ( ORDER BY anyelement ) → anyelement

計算離散分位數,即有序集聚合引數值中,其位置等於或超過指定 fraction 的第一個值。聚合引數必須是可排序的型別。

percentile_disc ( fractions double precision[] ) WITHIN GROUP ( ORDER BY anyelement ) → anyarray

計算多個離散分位數。結果是一個與 fractions 引數相同維度的陣列,每個非 NULL 元素都替換為對應於該分位數的輸入值。聚合引數必須是可排序的型別。


列在表 9.65中的每個假設集聚合都與同名的視窗函式相關聯,該函式定義在第 9.22 節中。在每種情況下,聚合的結果是關聯視窗函式對於從 args 構建的假設行返回的值,如果該行已新增到由 sorted_args 表示的行的排序組中。對於這些函式中的每一個,args 中的直接引數列表必須與 sorted_args 中的聚合引數的數量和型別匹配。與大多數內建聚合函式不同,這些聚合函式不是嚴格的,即它們不會丟棄包含 NULL 的輸入行。NULL 值根據 ORDER BY 子句中指定的規則進行排序。

表 9.65. 假設集聚合函式

函式

描述

部分模式

rank ( args ) WITHIN GROUP ( ORDER BY sorted_args ) → bigint

計算假設行的排名,帶間隙;也就是說,同一對(peer)行的行號。

dense_rank ( args ) WITHIN GROUP ( ORDER BY sorted_args ) → bigint

計算假設行的排名,不帶間隙;此函式有效地計算對(peer)組的數量。

percent_rank ( args ) WITHIN GROUP ( ORDER BY sorted_args ) → double precision

計算假設行的相對排名,即 (rank - 1) / (總行數 - 1)。因此,該值範圍從 0 到 1。

cume_dist ( args ) WITHIN GROUP ( ORDER BY sorted_args ) → double precision

計算累積分佈,即(排在假設行之前或與其同級的行數)/(總行數)。因此,該值範圍從 1/N 到 1。


表 9.66. 分組操作

函式

描述

GROUPING ( group_by_expression(s) ) → integer

返回一個位掩碼,指示哪些 GROUP BY 表示式未包含在當前分組集中。位分配方式是,最右邊的引數對應於最低有效位;如果對應的表示式包含在生成當前結果行的分組集的標準中,則該位為 0,如果不包含,則為 1。


表 9.66 中顯示的分組操作用於與分組集(參見第 7.2.4 節)結合使用,以區分結果行。 GROUPING 函式的引數實際上不會被評估,但它們必須與關聯查詢級別的 GROUP BY 子句中給出的表示式完全匹配。例如:

=> SELECT * FROM items_sold;
 make  | model | sales
-------+-------+-------
 Foo   | GT    |  10
 Foo   | Tour  |  20
 Bar   | City  |  15
 Bar   | Sport |  5
(4 rows)

=> SELECT make, model, GROUPING(make,model), sum(sales) FROM items_sold GROUP BY ROLLUP(make,model);
 make  | model | grouping | sum
-------+-------+----------+-----
 Foo   | GT    |        0 | 10
 Foo   | Tour  |        0 | 20
 Bar   | City  |        0 | 15
 Bar   | Sport |        0 | 5
 Foo   |       |        1 | 30
 Bar   |       |        1 | 20
       |       |        3 | 50
(7 rows)

在此,前四行的 grouping0 表明它們是正常分組的,按兩個分組列進行分組。值 1 表示在倒數第二行中 model 未被分組,而值 3 表示在最後一行中 makemodel 都未被分組(因此該行是對所有輸入行的聚合)。

提交更正

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