Chapter 7. SQLの拡張: 集約

Postgres における集約は状態遷移関数 の集合で表現されています。つまり、1 つの集約はインスタンスの処 理により変更された状態として定義することができます。 いくつかの状態関数は、インスタンス内のある特定の値を、新しい状 態への演算を行う時に(create aggregate 構文上の sfunc1 )参照します。 一方その他の状態関数は、その関数内の内部状態のみで演算 (sfunc2)を行います。 もし sfunc1 のみを使用して集約を定義すると、 それぞれのインスタンスの属性値に対して連続的に処理する関数を実行 する集約を定義することになります。"Sum" はこの種の集約の例です。 "Sum" は 0 から始まり、現在のインスタンスの値をその時点までの総和 に足し続けます。 このような足算を実行する方法としては Postgres に組み込まれた int4pl を使い ます。

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)   |
         +------------+

sfunc2 のみで集約を定義すると、それぞれのイ ンスタンスに対して属性値によらない連続的な処理を行なう関数を実 行する集約を定義していることとなります。 "Count" はこの種の集約でもっとも一般的な例です。 "Count" は 0 から始まり、インスタンス毎にその時点での回数を 1 増 やします。インスタンスが持つ値は無視します。この足算の実行に は、組込まれた int4inc 関数を使用します。 この関数はその引数をインクリメントします( 1 を足します)。

CREATE AGGREGATE my_count (
    sfunc2 = int4inc, -- 1 を足します
    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,     --  属性値の総和算出
    basetype = int4,
    stype1 = int4,
    sfunc2 = int4inc,    -- インスタンス総数算出
    stype2 = int4,
    finalfunc = int4div, -- 除算
    initcond1 = '0',
    initcond2 = '0'
);

SELECT my_average(salary) as emp_average FROM EMP;

         +------------+
         |emp_average |
         +------------+
         |1640        |
         +------------+