集計結果を条件で絞りたい
HAVING は集計後のグループを絞ります。まず社員が2人以上いる部署を探し、続いてWHEREで集計対象を変えた場合を3段階の表で比べます。
SQL例の例
SELECT department_id, COUNT(*) AS employee_count
FROM employees
GROUP BY department_id
HAVING COUNT(*) >= 2
ORDER BY department_id;この例で使うサンプル表を見る共通の架空データと、練習用の表を確認します
全20項目で共通の架空データです。salary は月給(円)。NULL は未設定を表します。結果の小数点以下の表示桁数は実行環境により異なります。
employees
| id | name | department_id | salary |
|---|---|---|---|
| 1 | 佐藤 | 1 | 300000 |
| 2 | 鈴木 | 2 | 400000 |
| 3 | 佐々木 | 1 | 350000 |
| 4 | 高橋 | 2 | 400000 |
| 5 | 田中 | NULL | 250000 |
| 6 | 伊藤 | 3 | NULL |
departments
| id | name |
|---|---|
| 1 | 営業 |
| 2 | 開発 |
| 3 | 人事 |
| 4 | 広報 |
employees.department_id が departments.id に対応します。表は説明用です。このサイト上でSQLは実行しません。
使い方を順番に確認する練習を始めるときは、この手順に沿って進めます
使い方
- 部署IDごとに社員数を数える
- HAVING COUNT(*) >= 2 を指定する
- 営業部と開発部のIDが残ることを確認する
結果の例
| department_id | employee_count |
|---|---|
| 1 | 2 |
| 2 | 2 |
WHEREは集計前の行、HAVINGは集計後のグループを絞ります。下の3段階は理解のために別々のSELECTで確認する例です。最後のSQLだけでも結果が得られます。実際のDB内部の物理的な実行順序を保証する図ではありません。
同じ6行から、WHERE → GROUP BY → HAVINGを確認する
1. WHERE:月給35万円以上の3行を残す
SELECT id, name, department_id, salary
FROM employees
WHERE salary >= 350000
ORDER BY id;上の共通サンプル6行をそのまま使います。鈴木・佐々木・高橋の3人が対象です。佐藤・田中は35万円未満、伊藤はsalaryがNULLなので、この条件を満たす行には入りません。元の表から削除する処理ではありません。
| id | name | department_id | salary |
|---|---|---|---|
| 2 | 鈴木 | 2 | 400000 |
| 3 | 佐々木 | 1 | 350000 |
| 4 | 高橋 | 2 | 400000 |
2. GROUP BY:残った3行を部署別の2グループにする
SELECT department_id, COUNT(*) AS employee_count
FROM employees
WHERE salary >= 350000
GROUP BY department_id
ORDER BY department_id;同じWHERE条件を残し、部署IDごとに数えます。部署1(営業)は佐々木の1人、部署2(開発)は鈴木・高橋の2人です。COUNT(*)は全社員6人ではなく、WHEREを通った行を各部署で数えています。
| department_id | employee_count |
|---|---|
| 1 | 1 |
| 2 | 2 |
3. HAVING:2人以上の1グループだけを残す
SELECT department_id, COUNT(*) AS employee_count
FROM employees
WHERE salary >= 350000
GROUP BY department_id
HAVING COUNT(*) >= 2
ORDER BY department_id;最後にHAVINGを加えます。部署1は1人なので表示されず、部署2の2人だけが残ります。冒頭のWHEREなしの例では部署1・2が残りましたが、こちらは「月給35万円以上の社員が2人以上いる部署」を探すSQLです。
| department_id | employee_count |
|---|---|
| 2 | 2 |
うまくいかないときに確認するエラーや想定と違う結果が出たときの確認ポイント
うまくいかないとき
WHERE COUNT(*) >= 2 と同じSELECTの集計を直接WHERE条件に書くとエラーになります。人数の条件はHAVINGへ書き、salary >= 350000 はWHEREに残してください。0行ならエラーとは限らず、条件を満たすグループがない可能性があります。ORDER BYを外した結果の並び順は保証されません。
PostgreSQLの構文を基準にしています。MySQL・SQL Server・SQLiteなどでは、一部の構文や挙動が異なります。
PostgreSQL:WHEREとHAVING、集約関数の関係