HAVING 句の使い方
shain社員
| busho_id | salary |
|---|---|
| 1 | 980000 |
| 2 | 720000 |
| 2 | 530000 |
| 2 | 520000 |
| … | |
GROUP BYまとめた結果
| busho_id | count(salary) |
|---|---|
| 1 | 1 |
| 2 | 4 |
| 3 | 4 |
| … | |
GROUP BY busho_id
- 社員 16 行 が、6 行にまとまります(同じ busho_id の行が 1 行になる)。
- count(salary)はまとまりごとに計算した値で、元の表には無い列です。
HAVING は、この右側の表に対して条件を付けます。左側(元の行)には効きません。
HAVING は「まとめた後の行」に条件を付ける場所です。 WHERE はまとめる前、HAVING はまとめた後。この順番だけが両者の違いで、そこから使い分けがすべて決まります。
主要 7 製品で通用 そのまま使える: PostgreSQL / MySQL / MariaDB / SQLite / SQL Server / Oracle Database / IBM Db2
このページの実行結果と図は、すべて本物のデータベースに同じ SQL を流して得たものです。手で書いた「たぶんこうなる」ではありません。
01評価される順番がすべて
結論: `WHERE` → `GROUP BY` → `HAVING` の順に処理されます。
この順番から、次のことが自動的に決まります。
WHEREでは集約関数が使えない(まだまとめていないのでcount(*)の値が存在しない)HAVINGでは集約した値が使える(すでにまとめた後だから)WHEREで落とした行は、集計にも入らない
「在籍者だけで数える」なら WHERE。「2 人以上の部署だけ出す」なら HAVING です。
SELECT busho_id, count(*) AS ninzuまとまりごとに数えるFROM shainどの表を見るかWHERE taishoku_on IS NULL① まとめる前に絞るGROUP BY busho_id② まとめるHAVING count(*) >= 3③ まとめた後に絞るORDER BY ninzu DESC並び順
①②③ の順に効きます。この順番を思い出せば、どちらに書くかで迷いません。
SELECT busho_id, count(*) AS ninzu
FROM shain
WHERE taishoku_on IS NULL
GROUP BY busho_id
HAVING count(*) >= 3
ORDER BY ninzu DESC, busho_id;| busho_id | ninzu |
|---|---|
| 2 | 4 |
| 3 | 3 |
(2 行)
02⚠️ よくある間違い:WHERE に集約関数を書くとエラーになる
「3 人以上の部署」を出したくて WHERE count(*) >= 3 と書くと、エラーになります。
WHERE が効く時点ではまだ行がまとまっていないので、count(*) という値がそもそも存在しないためです。
エラーメッセージは「集約関数は WHERE では使えない」と、原因をそのまま言ってくれます。`HAVING` に移せば直ります。
SELECT busho_id, count(*)
FROM shain
WHERE count(*) >= 3
GROUP BY busho_id;「集約関数は WHERE 句では使えない。おそらく HAVING に書くべき」と提案までしてくれます。
03⚠️ よくある間違い:逆に、まとめる前の条件を HAVING に書かない
HAVING にも普通の列の条件は書けてしまいます。エラーにはなりません。ただし書くべきではありません。
理由は 2 つあります。
- 意味が変わることがある。
WHEREなら集計から除かれますが、HAVINGはまとまった後の判定なので、集計値そのものは除外前の値のままになりえます - 無駄が多い。先に絞れる行を最後まで持ち回るので、行数が多いほど遅くなります
行の条件は `WHERE`、集約の条件は `HAVING` と機械的に割り振ってください。
SELECT busho_id, count(*) AS ninzu, max(salary) AS saikou
FROM shain
GROUP BY busho_id
HAVING max(salary) >= 600000
ORDER BY busho_id;| busho_id | ninzu | saikou |
|---|---|---|
| 1 | 1 | 980000 |
| 2 | 4 | 720000 |
| 3 | 4 | 700000 |
| 4 | 3 | 650000 |
| 5 | 2 | 610000 |
(5 行)
「最高給与が 60 万以上の部署」は、まとめないと分かりません。だから HAVING です。
04⚠️ よくある間違い:SELECT で付けた別名が使えるかは製品による
HAVING ninzu >= 3 のように別名で書けるかどうかは製品によって違います。標準では使えず、PostgreSQL でもエラーになります。
理由は評価順です。HAVING は SELECT より前に効くので、その時点ではまだ別名が作られていません。
確実なのは、式をそのまま書くことです。HAVING count(*) >= 3 と書けばどの製品でも通ります。
(ORDER BY は SELECT の後なので、別名が使えます。ここが紛らわしいところです。)
SELECT busho_id, count(*) AS ninzu
FROM shain
GROUP BY busho_id
HAVING ninzu >= 3;「ninzu なんて列は無い」と言われます。HAVING の時点では別名がまだ存在しません。
05GROUP BY 無しでも書ける
GROUP BY を書かずに集約関数を使うと、表全体が 1 つのまとまりになります。この場合も HAVING は使えます。
条件が真なら 1 行、偽なら 0 行が返ります。「全体の件数が 10 件を超えていたら結果を返す」といった、しきい値の判定に使えます。
使う機会は多くありませんが、HAVING が「まとまりに対する条件」であることの確認になります。
SELECT count(*) AS zenin, avg(salary)::numeric(10,0) AS heikin
FROM shain
HAVING count(*) >= 10;| zenin | heikin |
|---|---|
| 18 | 542003 |
(1 行)
条件を満たすので 1 行返ります。>= 100 に変えると 0 行になります(その場に打って試せます)。
自分で打ってみる
このページの例と同じデータが入った本物のデータベースを、この場(あなたのブラウザの中)で起動できます。打った SQL がサーバーへ送られることはありません。
押すと初回だけ約 9MB を読み込みます(2 回目以降はキャッシュされます)。
解いてみる
読んだだけでは書けるようになりません。実行結果で採点します。
関連するトピック
- GROUP BY 句HAVING は GROUP BY とセットで使います。
- WHERE 句まとめる前の絞り込み。順番の違いが使い分けの決め手です。
- 集約関数(練習問題)HAVING に書く条件は、たいてい集約関数です。
根拠(一次情報)
- PostgreSQL 18 マニュアル: 問い合わせ — GROUP BY と HAVING 句一次情報・確認 2026-07-28
- PostgreSQL 18 マニュアル: 集約関数一次情報・確認 2026-07-28
- SQLite: SELECT(HAVING clause)一次情報・確認 2026-07-28