VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
WHERE はグループ化される前に行を除外します。HAVING はグループが作られた後に
グループ全体を除外します。この 1 文がこのレッスンのすべてであり、以下はすべて
その帰結です。
始める前に mysql -u root -p sakila でクライアントを開いてください。
HAVING の仕組み
GROUPING_COLUMN をグループを定義する列に、TABLE_NAME をテーブルに、
AGGREGATE_FUNCTION(COLUMN_NAME) をグループごとに求めたいものに、
GROUP_CONDITION を COUNT(*) > 200 のようなグループ全体に適用する条件に
置き換えます。
サーバーはまずすべてのグループを作り、次に条件が真であるグループだけを
残します。
例
- 大きなグループだけを残す
- HAVING ではエイリアスを使える
エイリアスは結果の列に名前を付けるものであり、HAVING が実行される時点では
結果が存在しています。
WHERE にはこれができません。
名前を付ける対象となる結果が存在する前に実行されるためです。
WHERE のレッスンでは、代わりに返される ERROR 1054 を
示しています。
- 両方の句を 1 つのクエリで使う
実際のクエリの多くは両方を使います。WHERE で行を選び、HAVING でグループを
選びます。
WHERE が 120 分を超える映画を残し、グループ化がレーティングごとにそれを
数え、HAVING が 100 本を超える 1 つのレーティングを残しました。
集計関数は WHERE には書けない
先ほどのHAVING 条件を WHERE に移すと、サーバーはそれを即座に拒否します。
WHERE はグループ化の前に実行されるため、テストすべき件数がまだありません。
集計関数のエイリアスにも同じことが当てはまりますが、エラーは異なります。
HAVING に移します。
WHERE のエイリアスで出る ERROR 1054 には 2 つの対処法があり、集計関数か
どうかで区別します。単純な式のエイリアスは WHERE で式を繰り返して書けます。
これは WHERE のレッスンで示しています。集計関数の
エイリアスは、上記の ERROR 1111 のため、そこで繰り返すことがまったく
できないので、HAVING に移す必要があります。
どの句が何をテストするか
行をテストする条件は常に
WHERE に置き、HAVING はグループが存在して
初めて意味を持つものに限ってください。それがコストの低い構成でもあります。
その理由は
MySQL の GROUP BY のパフォーマンスガイドで
計測しています。
HAVING で選択リストのエイリアスを指定するのは MySQL の拡張です。同じ SQL を
別のデータベースでも実行する必要がある場合は、エイリアスではなく集計関数を
繰り返して書いてください。まとめ
- グループ全体を除外するには
HAVINGを、行を除外するにはWHEREを使います。 HAVINGはGROUP BYの後に実行されるため、集計関数をテストできます。ERROR 1111は、HAVINGに書くべき集計関数がWHEREにあるという意味です。HAVINGでは列のエイリアスを指定できます。WHEREにはできません。- グループではなく行をテストする条件は
WHEREに置きます。
関連項目
- GROUP BY — この句が絞り込むグループを作る
- WHERE — 先に実行される句
- 集計関数 — グループ条件が通常テストするもの
- MySQL の GROUP BY のパフォーマンス — 絞り込む前にグループ化するコスト