SQLのHAVINGとは?集計結果の絞り込みとWHEREの違いを解説
HAVINGは、集計した結果を条件で絞る構文です。「社員が2人以上いる部署」のように、数えてから判断する条件に使います。まず全部署の集計を見て、条件を付けるとどの部署が残るかを確認しましょう。
例で使う表
employeesの1行が社員1人分です。営業が2人、開発が2人、サポートが1人います。salaryは月給(円)で、恵比寿さんのNULLは月給が未入力であることを表し、0円とは区別します。すべての例でこの5人を使います。結果表の行の並びは一例です。ORDER BYで指定しない限り、表示順は保証されません。
| id(社員ID) | name(名前) | department(部署) | salary(月給) |
|---|---|---|---|
| 1 | 青木 | 営業 | 300000 |
| 2 | 北野 | 開発 | 400000 |
| 3 | 中央 | 営業 | 350000 |
| 4 | 大和 | 開発 | 400000 |
| 5 | 恵比寿 | サポート | NULL |
HAVINGの基本構文
SELECT department, COUNT(*) AS people
FROM employees
GROUP BY department
HAVING COUNT(*) >= 2;まずGROUP BYで全部署の人数を確認する
HAVINGを付ける前に、部署ごとの人数を出します。営業2人、開発2人、サポート1人の3行です。この集計結果を出発点に、次の節で「2人以上」という条件を付けます。
SELECT department, COUNT(*) AS people
FROM employees
GROUP BY department;| department | people |
|---|---|
| サポート | 1 |
| 営業 | 2 |
| 開発 | 2 |
HAVING COUNTで2人以上の部署を選ぶ
GROUP BYの後ろにHAVING COUNT(*) >= 2を足します。集計した人数を比べるので、営業と開発が残り、1人のサポートは外れます。WHERE COUNT(*) >= 2とは書けません。集計結果を条件にする場所がHAVINGです。
SELECT department, COUNT(*) AS people
FROM employees
GROUP BY department
HAVING COUNT(*) >= 2;| department | people |
|---|---|
| 営業 | 2 |
| 開発 | 2 |
HAVING SUMで月給の合計が70万円以上の部署を選ぶ
人数ではなく月給の合計を条件にするにはSUM(salary)を使います。営業は650000円、開発は800000円なので、開発だけが残ります。個人の月給が700000円以上かどうかではなく、部署全体の合計を比べています。
SELECT department, SUM(salary) AS total_salary
FROM employees
GROUP BY department
HAVING SUM(salary) >= 700000;| department | total_salary |
|---|---|
| 開発 | 800000 |
WHEREで月給35万円以上の社員だけを集計する
WHEREとHAVINGの違いを見るため、まずWHEREだけを使います。集計前に社員を絞るので、営業の青木さんは外れます。残った中央さんで営業1人、北野さんと大和さんで開発2人になります。
SELECT department, COUNT(*) AS people
FROM employees
WHERE salary >= 350000
GROUP BY department;| department | people |
|---|---|
| 営業 | 1 |
| 開発 | 2 |
WHEREとHAVINGを組み合わせる
前の結果にHAVING COUNT(*) >= 2を加えます。月給35万円以上の社員だけをWHEREで選び、その人数が2人以上の部署をHAVINGで残します。営業は1人になっているため外れ、開発だけが表示されます。
SELECT department, COUNT(*) AS people
FROM employees
WHERE salary >= 350000
GROUP BY department
HAVING COUNT(*) >= 2;| department | people |
|---|---|
| 開発 | 2 |
ANDで集計結果の条件を2つ指定する
人数が2人以上で、平均月給も350000円以上の部署を選びます。営業は2人ですが平均325000円なので外れます。開発は2人、平均400000円で両方を満たします。SELECTに判定に使う値を出すと、残った理由を確認できます。
SELECT department, COUNT(*) AS people,
AVG(salary) AS average_salary
FROM employees
GROUP BY department
HAVING COUNT(*) >= 2
AND AVG(salary) >= 350000;| department | people | average_salary |
|---|---|---|
| 開発 | 2 | 400000 |
実際に1問解いてみる
HAVING COUNT
社員が2人以上の部署と人数をdepartment、COUNT(*)の順で取得してください。行順は問いません。
テーブル
読み込み中…
実行結果
関連構文
HAVINGについてよくある質問
- GROUP BYなしでもHAVINGは使えますか?
- 使えます。表全体を1つのグループと見なします。今回の表でSELECT COUNT(*) FROM employees HAVING COUNT(*) >= 5;なら5を含む1行が返り、条件を>= 6にすると0行になります。
- 平均がNULLの部署は比較条件に残りますか?
- AVG(salary) >= 350000のような比較では残りません。月給が全員未入力の部署を探すなら、HAVING AVG(salary) IS NULLで判定します。
参考文献
内容はPostgreSQL公式ドキュメントを参照し、初めて学ぶ人向けに日本語で整理しています。
- PostgreSQL公式:GROUP BYとHAVING — GROUP BYとHAVINGの仕様と使用例
- PostgreSQL公式:SELECT — SELECTの仕様と使用例
- PostgreSQL公式:集約関数 — 集約関数の仕様と使用例