PostgreSQLのHAVING句を徹底解説!WHERE句との違いやSQLクエリの書き方
生徒
「集計したデータに対して、さらに条件を絞りたいときはどうすればいいんですか?例えば、各部署の平均給与を出したあと、さらに『平均が30万円以上の部署だけ』を表示したいんです。」
先生
「それは非常に重要な視点ですね。実は、いつものWHERE句(ウェアく)では集計した後の結果には条件をかけられないんです。そこで登場するのが『HAVING句(ハビングく)』ですよ。」
生徒
「HAVING句……。WHERE句とは何が違うんでしょうか?難しそうです。」
先生
「難しくありませんよ。WHEREは『集計する前の個別のデータ』をチェックし、HAVINGは『集計した後のグループの結果』をチェックします。料理に例えると、WHEREは『痛んだ野菜を調理前に捨てること』、HAVINGは『出来上がった料理の中から味が濃すぎるものだけを取り除くこと』に似ています。」
1. SQLとは何か?
SQL(エスキューエル)は、データベースと呼ばれる「大量のデータを整理して保存する箱」に対して指示を出すための言語です。例えば、会員名簿の中から特定の人を探したり、新しい人を追加したりするときに使います。パソコンの操作が苦手な方でも、「命令の書き方のルール」さえ覚えれば、誰でも複雑なデータの中から必要な情報だけを魔法のように取り出すことができます。
PostgreSQL(ポストグレスキューエル)は、そのSQLを使ってデータを管理するためのシステムの一つで、世界中の企業やサービスで使われている非常に信頼性の高いツールです。今回は、その中で「データの集計」に欠かせないHAVING句という命令について詳しく見ていきましょう。
2. HAVING句の役割と基本の仕組み
データベースを操作していると、「データを合計する(SUM)」や「平均を出す(AVG)」、「データの個数を数える(COUNT)」といった「集計(しゅうけい)」という作業を頻繁に行います。この集計作業には「GROUP BY句(グループバイく)」という命令をセットで使いますが、その集計した結果に対して「さらに条件をつけたい」ときに使うのがHAVING句です。
初心者が一番つまずきやすいのが、「条件ならWHERE句でいいんじゃないの?」という点です。しかし、SQLには厳格な実行順序というルールがあります。コンピュータはまずWHERE句でデータを絞り込み、その後に集計を行います。そのため、集計が終わった後の数値(合計値や平均値など)を使って絞り込みを行いたい場合は、WHERE句ではなく、集計専用のフィルターであるHAVING句を使う必要があるのです。
3. 実践1:売上の合計金額でグループを絞り込む
それでは、具体的な例で見ていきましょう。まずは、お店の注文データが入った「orders」というテーブル(表)があるとします。ここには、どの顧客がいくら買い物したかが記録されています。
id | customer_name | amount | category
---+---------------+--------+----------
1 | 田中さん | 1500 | 食品
2 | 佐藤さん | 3000 | 雑貨
3 | 田中さん | 2000 | 飲料
4 | 鈴木さん | 5000 | 家電
5 | 佐藤さん | 1200 | 食品
6 | 田中さん | 800 | 雑貨
このデータから、「合計の注文金額が4000円以上の顧客」だけをリストアップしてみましょう。ここで使うのがHAVING句です。注文金額(amount)を顧客(customer_name)ごとに合計し、その結果が4000円より大きい人だけを表示します。
SELECT customer_name, SUM(amount) AS total_amount
FROM orders
GROUP BY customer_name
HAVING SUM(amount) >= 4000;
このSQLを実行すると、コンピュータはまず顧客ごとに金額を足し算します。田中さんは1500+2000+800=4300円、佐藤さんは3000+1200=4200円、鈴木さんは5000円となります。その後、HAVING句によって「4000円以上の人」という条件がチェックされます。この例では全員が残りますね。
customer_name | total_amount
--------------+--------------
田中さん | 4300
佐藤さん | 4200
鈴木さん | 5000
4. WHERE句とHAVING句を同時に使う方法
次に、WHERE句とHAVING句の両方を使った、より実践的なクエリを見てみましょう。SQLのルールでは、WHERE → GROUP BY → HAVING の順番で記述します。役割分担は以下の通りです。
- WHERE句:集計する前の、個々の行(データ)を絞り込む。
- HAVING句:集計した後の、グループごとの結果を絞り込む。
例えば、「食品以外のカテゴリー」を対象に、「合計金額が4000円以上の顧客」を探すとします。まず「食品以外」という条件は、集計前に個別のデータを見て判断できるのでWHERE句を使います。その後、残ったデータで合計を出し、HAVING句で絞り込みます。
id | customer_name | amount | category
---+---------------+--------+----------
1 | 田中さん | 1500 | 食品
2 | 佐藤さん | 3000 | 雑貨
3 | 田中さん | 2000 | 飲料
4 | 鈴木さん | 5000 | 家電
5 | 佐藤さん | 1200 | 食品
6 | 田中さん | 800 | 雑貨
SELECT customer_name, SUM(amount) AS total_amount
FROM orders
WHERE category != '食品'
GROUP BY customer_name
HAVING SUM(amount) >= 4000;
この場合、ID 1とID 5の「食品」データがまずWHERE句で除外されます。その状態で合計を計算するため、結果は以下のようになります。
customer_name | total_amount
--------------+--------------
鈴木さん | 5000
田中さんは食品を除くと2800円、佐藤さんは3000円になり、HAVING句の「4000円以上」という条件を満たさなくなるため、表示されなくなります。このように、WHEREとHAVINGを使い分けることで、非常に細かなデータ分析が可能になります。
5. 実践2:データの個数(COUNT)で条件を指定する
HAVING句は、合計金額だけでなく「データの件数」に対しても使えます。例えば、学校のテスト結果を管理する「exam_results」テーブルがあるとしましょう。ここで「3回以上テストを受けた生徒」だけを抽出したい場合に便利です。
id | student_name | score | exam_date
---+--------------+-------+------------
1 | 山田太郎 | 80 | 2023-04-01
2 | 佐藤花子 | 95 | 2023-04-01
3 | 山田太郎 | 70 | 2023-05-01
4 | 鈴木一郎 | 60 | 2023-05-01
5 | 山田太郎 | 85 | 2023-06-01
6 | 佐藤花子 | 88 | 2023-06-01
7 | 田中次郎 | 50 | 2023-06-01
このデータを使って、受験回数が3回以上の生徒を見つけるSQLを書きます。データの個数を数える「COUNT(カウント)」関数とHAVING句を組み合わせます。
SELECT student_name, COUNT(*) AS exam_count
FROM exam_results
GROUP BY student_name
HAVING COUNT(*) >= 3;
実行結果は以下の通りです。山田太郎さんだけが3回受験しているため、彼だけが表示されます。佐藤花子さんは2回、鈴木一郎さんと田中次郎さんは1回なので除外されます。
student_name | exam_count
-------------+------------
山田太郎 | 3
6. 注意点:HAVING句でよくある間違い
初心者が最も間違いやすいポイントは、「HAVING句に集計関数を使わない列の条件を書いてしまうこと」です。例えば、先ほどの注文データで「HAVING category = '食品'」と書くのは間違いです。カテゴリーという情報は、集計する前の個別のデータが持っている性質なので、WHERE句に書かなければなりません。
逆に、WHERE句の中に「WHERE SUM(amount) > 1000」と書くこともできません。コンピュータはWHERE句を処理する時点では、まだ合計金額(SUM)を知らないからです。SQLを書くときは、「今、自分がかけようとしている条件は、計算する前のデータに対するものか、計算した後の結果に対するものか」を一度立ち止まって考えてみてください。
また、PostgreSQLでは、SELECT句でつけた名前(エイリアス)をHAVING句で直接使えない場合があることにも注意が必要です。基本的には「HAVING SUM(column)」のように、計算式をそのまま記述するのが最も確実で安全な書き方です。これを意識するだけで、エラーに悩まされる回数がぐっと減るはずです。
データベース操作は、一見すると英語のような呪文に見えますが、その正体は非常に論理的でシンプルなパズルです。HAVING句をマスターすれば、膨大なデータから「平均以上の成績の人」「特定の回数以上購入した優良顧客」など、価値のある情報を自由自在に引き出せるようになります。まずは基本の形を何度も書いて、指に馴染ませていきましょう。