PostgreSQL7.0手冊-程序員手冊 -41. 擴展的 SQL: 聚集
2019-09-08 23:33:46
供稿:網友
第四十一章. 擴展的 SQL: 聚集
在 Postgres 里的聚集是用狀態值和狀態轉換函數表達的.也就是說,一個聚集可以定義為一些狀態,當一條輸入的條目被處理時,這些狀態被修改.要定義一個新的聚集函數,我們就要選擇一個表示狀態值的數據類型,一個狀態初始值,一個狀態轉換函數.該狀態轉換函數只是一個普通函數,也可以用于聚集的環境之外.
實際上,為了便于從現有的函數里構造聚集,一個聚集可以有一到兩個獨立的狀態值,一到兩個用于更新那些狀態值的轉換函數,和一個最終函數用于從最終狀態值中計算實際的聚集結果.
這樣我們可能最多要涉及到四種數據類型:輸入條目的類型,聚集結果的類型和兩個狀態值的類型.聚集的用戶之能看到輸入和結果數據類型.
有些狀態轉換函數需要獲取每個連續的輸入以計算下一個狀態值,而另外一些忽略聲明的輸入并簡單地更新內部狀態.(第二種情況最常用的例子是對一些輸入條目運行計數統計.)Postgres 的聚集機制為聚集把 sfunc1 定義為一個傳遞舊狀態值和當前輸入值的函數,而 sfunc2 是一個只傳遞舊狀態值的函數.
如果我們定義了一個只使用 sfunc1 的聚集,我們就定義了一個對每條記錄字段值運行函數進行計算的函數."Sum" 是這種聚集的一個例子."Sum" 從零開始,然后總是把當前記錄的值加到它(運行時的)總和上.例如,如果我們想做一個能對復數類型進行 Sum?。ㄇ蠛停┻\算的聚集,我們只需要那個數據類型的累加函數.聚集的定義是:
CREATE AGGREGATE complex_sum (
sfunc1 = complex_add,
basetype = complex,
stype1 = complex,
initcond1 = '(0,0)'
);
SELECT complex_sum(a) FROM test_complex;
+------------+
|complex_sum |
+------------+
|(34,53.9) |
+------------+
(實際上,我們會把這個聚集命名為 "sum",并依靠 Postgres 來區分對一個復數列應該施用哪種 sum.)
如果我們只定義 sfunc2,我們就聲明了一個計算的運行時數據與每條記錄的字段值無關的函數."Count" 是這種聚集的最通常的例子."Count" 從零開始然后每條記錄往它的運行時總數加一,不管記錄值是多少.這里,我們用內建的 int4inc 函數為我們做這件事.該函數往它的參數上加一.這里,我們使用內建的 int4inc 過程為我們完成這件事.這個過程對它的參數加一.
CREATE AGGREGATE my_count (
sfunc2 = int4inc, -- add one
basetype = int4,
stype2 = int4,
initcond2 = '0'
);
SELECT my_count(*) as emp_count from EMP;
+----------+
|emp_count |
+----------+
|5 |
+----------+
"Average" 是同時需要計算運行時的總和和運行時計數的聚集的例子.當所有記錄都處理過后,該聚集的最終結果就是用運行時總和除以運行時計數.我們用 int4pl 和 int4inc 函數和 Postgres 整數除法函數,int4div,來計算平均數.
CREATE AGGREGATE my_average (
sfunc1 = int4pl, -- sum
basetype = int4,
stype1 = int4,
sfunc2 = int4inc, -- count
stype2 = int4,
finalfunc = int4div, -- division
initcond1 = '0',
initcond2 = '0'
);
SELECT my_average(salary) as emp_average FROM EMP;
+------------+
|emp_average |
+------------+
|1640 |
+------------+
更詳細的信息請參考PostgreSQL 用戶手冊里的 CREATE AGGREGATE.
--------------------------------------------------------------------------------