メインコンテンツへスキップ

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 のようなグループ全体に適用する条件に 置き換えます。 サーバーはまずすべてのグループを作り、次に条件が真であるグループだけを 残します。

例

  1. 大きなグループだけを残す

5 つのレーティングすべてが数えられました。そのうち 3 つのグループが条件を 満たさず、除外されました。

  1. HAVING ではエイリアスを使える

エイリアスは結果の列に名前を付けるものであり、HAVING が実行される時点では 結果が存在しています。
同じ 2 行が返り、書く量は少なくなります。WHERE にはこれができません。 名前を付ける対象となる結果が存在する前に実行されるためです。 WHERE のレッスンでは、代わりに返される ERROR 1054 を 示しています。

  1. 両方の句を 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 に置きます。

関連項目