0Pricing
SQL Interview Prep · レッスン

HAVINGとWHEREの違い

グループ化の前後でのフィルタリングと、集計値を参照できる句を学びます。

「HAVINGとWHEREの違い」はCoddyKit上の無料SQL Interview Prepレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Interview Prepコースには全4レッスンが含まれています。

面接で問われる質問

「WHEREとHAVINGの違いは何ですか?」は、SQLの面接で最もよく聞かれる質問の一つです。弱い回答は「HAVINGは集約関数用です」と答えます。強い回答では、クエリの処理パイプラインで各句がいつ実行されるかを説明します。

すべてのポイントはそのタイミングにあります。WHEREはグループ化の前に行を絞り込み、HAVINGは集約の後にグループを絞り込みます。

実行順序の中での位置

クエリの論理的な実行順序を思い出しましょう。

  • FROM / JOIN → 行の集合を作成
  • WHERE → 個々の行を絞り込み
  • GROUP BY → グループにまとめる
  • HAVING → グループを絞り込み
  • SELECT → 列を射影
  • ORDER BY → 並べ替え

WHEREはグループが存在する前に実行され、HAVINGはその後に実行されます。そのため、HAVINGからは集約値を参照できますが、WHEREからは参照できません。

WHEREからは集約値を参照できない

WHEREはグループ化の前に実行されるため、まだ集約値が存在しません。WHERE COUNT(*) > 5と書くと、標準的なデータベースでは構文エラーになります。

面接官は、処理パイプラインを理解しているか確認するために、この記述をそのまま提示することがあります。WHEREの評価時点では、その集約値はまだ存在していません。

-- ERROR: aggregate not allowed in WHERE
SELECT department, COUNT(*)
FROM employees
WHERE COUNT(*) > 5
GROUP BY department;

HAVINGでグループを絞り込む

集約条件をHAVINGに移すと機能します。HAVINGは、グループとその集約値が計算された後に実行されるためです。

「従業員をグループ化し、人数が5人を超える部署だけを残す」と解釈してください。

SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;

行の絞り込みはWHEREに記述する

逆によくある間違いは、HAVINGで生の行を絞り込むことです。意図したとおりの結果になることも多いですが、破棄するはずの行までグループ化してしまうため、処理が遅く、意図も伝わりにくくなります。

目安は次のとおりです。生の列の値で絞り込む場合はWHERE、集約値で絞り込む場合はHAVINGです。行を早い段階で絞り込むと、グループ化が処理するデータ量を減らせます。

-- Better: drop inactive rows BEFORE grouping
SELECT department, COUNT(*) AS headcount
FROM employees
WHERE status = 'active'
GROUP BY department
HAVING COUNT(*) > 5;

両方の句を一緒に使う

完全なクエリでは、WHEREとHAVINGの両方を使うことがよくあります。まずWHEREで行を絞り込み、その後HAVINGで条件を満たすグループだけを残します。上から下へ読むと、論理的な実行順序と一致します。

例題:今年注文された商品のうち、合計金額が1000を超える顧客を見つけてください。

SELECT customer_id, SUM(amount) AS total_spent
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY customer_id
HAVING SUM(amount) > 1000;

集約されていない列に対するHAVING

HAVINGは集約値だけでなく、グループ化列を参照することもできます。HAVING department = 'Sales'は合法ですが、意味がありません。この条件はWHEREに置いて、より早い段階で実行すべきです。

面接官が通常のグループ化列を絞り込むHAVINGを示した場合、期待される指摘は「効率化のためにWHEREへ移す」です。

-- Works but inefficient; prefer WHERE department = 'Sales'
SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING department = 'Sales';

GROUP BYなしのHAVING

少し意外な点として、GROUP BYがなくてもHAVINGは合法です。テーブル全体が暗黙的な1つのグループになり、HAVINGはそのグループを絞り込みます。

集約条件が偽なら0行、真なら1行が返されます。実用性はあまりありませんが、面接官は暗黙のグループという概念を理解しているか確認するために質問します。

-- Returns the count only if the table has > 100 rows
SELECT COUNT(*) AS total
FROM orders
HAVING COUNT(*) > 100;

HAVINGでSELECTの別名を使えるか

別の場所で登場した別名のスコープに関する問題と同様に、方言によって異なります。PostgresとMySQLではHAVINGからSELECTの別名を参照できますが、SQL ServerとOracleではできません。

移植性を重視するなら、HAVINGで集約式を繰り返す習慣をつけましょう。どのエンジンでも機能し、複数データベースを扱う面接で予想外の問題を避けられます。

-- Portable: repeat the aggregate, do not rely on the alias
SELECT region, SUM(amount) AS total
FROM sales
GROUP BY region
HAVING SUM(amount) > 5000;

パフォーマンスの観点

説得力を高めるには、各句をパフォーマンスと結び付けて説明しましょう。WHEREはグループ化エンジンが走査する行数を減らし、インデックスも利用できます。一方、HAVINGはすでに集約されたグループに対して実行されるため、グループ化にかかるコストは削減できません。

面接官が求める要点は、すべての絞り込み条件を可能な限り早く適用することです。集約値に本当に依存する条件だけがHAVINGを必要とします。

一文で答えるなら

面接では次の一文を覚えておきましょう。「WHEREはグループ化の前に行を絞り込み、集約値を参照できません。HAVINGは集約の後にグループを絞り込み、集約値を条件にできる唯一の句です。」

続けて実行順序の一覧を説明すれば、完全でシニアらしい回答になります。

クイックチェック

それぞれの条件をどの句に置くべきか考えてみましょう。

まとめ

WHERE:GROUP BYの前に行を絞り込みます。集約値は使用できません。HAVING:集約の後にグループを絞り込み、集約条件を記述できる唯一の場所です。

  • 処理速度とインデックス利用のため、生の列に対する条件はWHEREに置きます。
  • HAVINGはグループ化列を参照できますが、単純な絞り込みには使うべきではありません。
  • HAVINGはGROUP BYなしでも、テーブル全体を対象とする暗黙のグループに対して機能します。
  • 複数の方言で安全に動作させるには、HAVINGで集約式を繰り返します。

よくある質問

「HAVINGとWHEREの違い」レッスンは無料ですか?

はい。「HAVINGとWHEREの違い」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Interview Prepコースには全4レッスンが含まれています。

「HAVINGとWHEREの違い」で何を学びますか?

グループ化の前後でのフィルタリングと、集計値を参照できる句を学びます。 ブラウザで直接実行するハンズオンコードでSQL Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

SQL Interview Prepを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSQL Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「HAVINGとWHEREの違い」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSQL Interview Prepレッスンでコードを書いて実行できますか?

はい。すべてのSQL Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. SELECT列に関するGROUP BYのルール
  2. HAVINGとWHEREの違い
  3. 複数列と式でグループ化する
  4. グループを数えてフィルタリングする
← SQL Interview Prepに戻る