無料スクリプト配布のPHP.TO   PHPの実用的なtips PHPマニュアル MySQLマニュアル Apacheマニュアル PostgreSQLマニュアル マニュアル検索    

2.7. 集約関数

他のほとんどのリレーショナルデータベース製品同様、 PostgreSQL 集約関数 をサポートします。 集約関数は複数の入力行から1つの結果を計算します。 例えば、行の集合に対して、 count (総数)、 sum (総和)、 avg (平均)、 max (最大)、 min (最小)といった演算を行う集約があります。

例として、次のように全ての都市の最低気温から最も高い気温を求めることができます。

SELECT max(temp_lo) FROM weather;

 max
-----
  46
(1 row)

どの都市のデータなのかを知りたいとしたら、下記のような問い合わせを試行するかもしれません。

SELECT city FROM weather WHERE temp_lo = max(temp_lo);     
間違い

しかし、 max 集約を WHERE で使用することができませんので、このコマンドは動作しません ( WHERE 句はどの行を集約処理に渡すのかを決定するものであり、したがって、集約関数の演算を行う前に評価されなければならないことは明らかです。 このためにこの制限があります)。 しかしたいていの場合、問い合わせを書き直すことで、意図した結果が得られます。 これには以下のような 副問い合わせ を使用します。

SELECT city FROM weather
    WHERE temp_lo = (SELECT max(temp_lo) FROM weather);

     city
---------------
 San Francisco
(1 row)

副問い合わせは、外側の問い合わせで起こることとは別々に集約を計算する独立した演算ですので、この問い合わせは問題ありません。

また、 GROUP BY 句と組み合わせた集約は非常に役に立ちます。 例えば、以下のコマンドで都市ごとに最低気温の最大値を求めることができます。

SELECT city, max(temp_lo)
    FROM weather
    GROUP BY city;

     city      | max
---------------+-----
 Hayward       |  37
 San Francisco |  46
(2 rows)

ここには都市ごとに1行の出力があります。 それぞれの集約結果は都市に一致するテーブル行全体に対する演算結果です。 以下のように、 HAVING を使用すると、グループ化された行にフィルタをかけることができます。

SELECT city, max(temp_lo)
    FROM weather
    GROUP BY city
    HAVING max(temp_lo) < 40;

  city   | max
---------+-----
 Hayward |  37
(1 row)

このコマンドは上と同じ計算を行うものですが、全ての temp_lo の値が40未満の都市のみを出力します。 最後になりますが、 " S " から始まる名前の都市のみを対象にしたい場合は、以下を行います。

SELECT city, max(temp_lo)
    FROM weather
    WHERE city LIKE 'S%'

(1)


    GROUP BY city
    HAVING max(temp_lo) < 40;

(1)
LIKE 演算子はパターン一致を行います。これについては 項9.7 で説明します。

集約と SQL WHERE HAVING 句の間の相互作用を理解することが重要です。 WHERE HAVING の基本的な違いを以下に記します。 WHERE は、グループや集約を演算する前に入力行を選択します(したがって、これはどの行を使用して集約演算を行うかを制御します)。 一方、 HAVING は、グループと集約を演算した後に、グループ化された行を選択します。 したがって、 WHERE 句は集約関数を持つことはできません。 集約を使用して、どの行をその集約の入力にするのかを決定することは意味をなしません。 一方で、 HAVING 句は常に集約関数を持ちます (厳密に言うと、集約を使用しない HAVING 句を書くことはできますが、これは有用となることはほぼありません。 同じ条件は WHERE の段階でもっと効率良く使用できます)。

前の例では WHERE 内に都市名制限を適用することができます。 集約を行う必要がないからです。 WHERE の検査で失敗する全ての行に対するグループ化や集約演算が行われませんので、 HAVING に制限を追加するよりも効率的です。


powered by SEO.CUG.NET