4.10. 集約関数の利用

その他のリレーショナルデータベース製品のように、 PostgreSQLも集約関数をサポートしていま す。集約関数は複数の入力行から単一の結果を計算するものです。例えば、 count, sum, avg (average), max (maximum) ,min (minimum) といった関数が一組の 行を計算して集計を行います。

集約と SQL のWHEREHAVING節 間の相互作用を認識することは重要です。WHEREHAVINGの基本的な違いは以下の通りです。 WHEREはグループ化と集約計算する前に入力された行 のセレクトをおこないます。(こうして、どの行が集約計算に入るかを制御 しています。)これに対してHAVINGは、グループ化と 集約計算を行った後のグループの行に対してセレクトを行います。したがって WHERE節は集約関数を含まないのです。つまり、どの 行が集合への入力であるかについて決定するために集約を使用することは 意味をなさないのです。もう一方では、HAVING節は 常に集約関数を含みます。(厳密にいうと、集約を使用しない HAVING節も記述できますが、効率がよくありません。 同じ条件ならWHERE 節を用いるとより効率的に使用 されます。)

例えば、最低気温の中で一番高いものを探すことができます。

SELECT max(temp_lo) FROM weather;
    
都市(複数かもしれません)に起こった事を知りたくて以下のような問い合 わせを試してみるかもしれません。
SELECT city FROM weather WHERE temp_lo = max(temp_lo);
    
しかし集約のmaxWHERE中で 使うことができないのでこの問い合わせはできません。しかしこの問い合 わせのケースはよくありますので、問い合わせを書き直せば、意図した結 果が得られます。これにはsubselectを使用しま す。
SELECT city FROM weather
    WHERE temp_lo = (SELECT max(temp_lo) FROM weather);
    
内側の選択が、外側の選択で起こっていることから、別にそれ自身の集 約を計算する独立した計算であるので、この問い合わせは可能です。

集約はGROUP BY節を組み合わせるとより有効です。 例えば、各々の都市における最低気温を得たい場合

SELECT city, max(temp_lo)
    FROM weather
    GROUP BY city;
    
とすると都市毎に一行の出力を行います。HAVINGを 使用することでグループ分けした行に対してフィルターをかけることがで きます。
SELECT city, max(temp_lo)
    FROM weather
    GROUP BY city
    HAVING min(temp_lo) < 0;
    
これは下記の 0 以下の値をもつ都市だけに対して同じ結果を返します。 最後に、「P」で始まる都市のみを検索したいのであればこのようにする かもしれません。
SELECT city, max(temp_lo)
    FROM weather
    WHERE city like 'P%'
    GROUP BY city
    HAVING min(temp_lo) < 0;
    
それ自体が集約を必要としないという理由からWHERE で都市名の制約を適用することができるという点に注意して下さい。これ は、HAVINGで制限をするよりも効果的です。それは、 WHEREでひっかからないすべての行のためにグループ 化と集計計算を行うことを避けられるからです。