SQL練習室
← SQLガイド

SQLのHAVINGとは?WHEREとの違い・複数条件・GROUP BYなしの使い方

HAVINGは、集計したグループを条件で絞る構文です。「2人以上の部署」のように、数えてから判断する条件に使います。WHEREとの違いを押さえ、合計額や複数条件で必要なグループだけを取り出しましょう。

HAVINGの基本構文

sql
SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING COUNT(*) >= 2;

HAVING COUNTで件数を条件にする

部署ごとの行数を数え、2件以上のグループだけを残します。1人の部署は結果から消えます。集約結果はWHEREの段階ではまだ条件にできないため、WHERE COUNT(*) >= 2とは書けません。

sql
SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING COUNT(*) >= 2;

HAVING SUMで合計額を条件にする

合計給与が100万円以上の部署を選ぶにはSUM(salary)を条件にします。個々の給与が100万円以上というWHERE条件とは別の意味です。HAVINGの集約式をSELECTに出すことは必須ではありませんが、表示すると絞り込みの理由を確認しやすくなります。

sql
SELECT department, SUM(salary)
FROM employees
GROUP BY department
HAVING SUM(salary) >= 1000000;

HAVING AVGで平均値を条件にする

AVG(salary) >= 500000なら部署平均が50万円以上の部署を返します。NULLの給与は平均の分母にも含まれません。全員が未入力の部署では平均がNULLになり、この比較を通過しない点に注意しましょう。

sql
SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) >= 500000;

WHEREとHAVINGの違い:集計前と集計後

在籍者だけを数え、その人数が2人以上の部署を選ぶなら、在籍条件をWHERE、人数条件をHAVINGに書きます。WHEREによって平均・件数の母集団そのものが変わります。「全社員の人数」と「在籍者の人数」を取り違えないことが大切です。

判定対象
WHERE集計前の行active = true
HAVING集計後のグループCOUNT(*) >= 2
sql
SELECT department, COUNT(*)
FROM employees
WHERE active = true
GROUP BY department
HAVING COUNT(*) >= 2;

HAVINGの複数条件:AND・ORとカッコ

人数と平均の両方を満たすにはAND、いずれかならORです。WHEREと同じくANDがORより優先されるので、混在するときはカッコで判断のまとまりを示します。まず各集約値をSELECTで表示してから条件を追加すると、意図したグループを残しているか確認できます。

sql
SELECT department, COUNT(*), AVG(salary)
FROM employees
GROUP BY department
HAVING COUNT(*) >= 2
  AND (AVG(salary) >= 500000 OR SUM(salary) >= 900000);

GROUP BYなしのHAVING:全体を1グループとして判定する

GROUP BYを省くと対象全体が1グループになります。HAVINGがtrueなら集約結果を1行、そうでなければ0行返します。全社人数が基準以上のときだけレポートを出す、といった全体判定に使えます。集計キーがないので、社員名などの明細列はそのまま出せません。

sql
SELECT COUNT(*)
FROM employees
HAVING COUNT(*) >= 5;

HAVINGでよくある間違い

SELECTの別名をHAVINGから参照する

PostgreSQLのHAVINGでは同じSELECTの出力別名を参照できません。HAVING people >= 2ではなくCOUNT(*) >= 2と書きます。別名で条件をまとめたい場合はサブクエリに分け、その外側のWHEREを使います。

sql
SELECT department, COUNT(*) AS people
FROM employees
GROUP BY department
HAVING COUNT(*) >= 2;

実際に1問解いてみる

HAVING COUNT

社員が2人以上の部署と人数をdepartmentCOUNT(*)の順で取得してください。行順は問いません。

テーブル

読み込み中…

実行結果

関連構文

HAVINGについてよくある質問

HAVINGとWHEREは両方使えますか?
使えます。WHEREをGROUP BYより前、HAVINGを後ろに書き、入力行の条件と集約値の条件を分けます。
HAVINGはSELECTにない集約関数も使えますか?
使えます。たとえば部署名だけを表示し、HAVING COUNT(*) >= 2で人数を判定できます。集計値を表示するかと、条件に使うかは別です。
HAVINGで平均がNULLの部署を探せますか?
HAVING AVG(salary) IS NULLで探せます。= NULLでは判定できません。グループ化された部署の給与がすべてNULLなら、この条件に一致します。

参考文献

内容はPostgreSQL公式ドキュメントを参照し、初めて学ぶ人向けに日本語で整理しています。