WHEREは集計前の行、HAVINGは集計後のグループを絞ります。副問い合わせは、別の検索結果を条件などに使う仕組みです。集計と存在チェックを、小さな表で順に確認しましょう。例は学習用の架空データです。
まず集計の材料になる行を確認
| sale_id | shop | amount |
|---|---|---|
| 1 | 東店 | 600 |
| 2 | 東店 | 900 |
| 3 | 西店 | 400 |
| 4 | 西店 | 700 |
sale_idは主キー、shop・amountはNULLではないものとします。
SELECT shop, SUM(amount) AS total
FROM sales
WHERE amount >= 500
GROUP BY shop
HAVING SUM(amount) >= 1000
ORDER BY SUM(amount) DESC;
400の行を除いてから店舗別に合計すると、東店1500・西店700です。HAVINGで1000以上を残すので、結果は東店1500の1行になります。これは結果を理解するための論理的な流れで、内部の物理的な実行順を固定する説明ではありません。
GROUP BY・HAVING・COUNTの確認点
| 項目 | 確認点 |
|---|---|
| GROUP BY | 同じ値の行をグループにまとめる |
| HAVING | グループや集計結果に条件を指定する |
| COUNT(*) | 行数を数える |
| COUNT(amount) | amountがNULLでない行を数える |
| SUM・AVG | 通常はNULLを除いて計算。AVGの分母もNULLでない値の数 |
基本の集計問題では、SELECTに書く列がグループ化のキーか集計結果かを確認します。SQLには関数従属などによる例外もあるため、製品の規則や問題の前提にも注意します。HAVINGでSELECTの別名を使えるかもDBMSによります。
年の条件は開始と終了を指定する
SELECT shop, SUM(amount)
FROM sales_table
WHERE sales_date >= DATE '2025-01-01'
AND sales_date < DATE '2026-01-01'
GROUP BY shop
HAVING SUM(amount) >= 100000;
2025年だけなら、開始日以降という条件だけでは2026年以降も含まれます。翌年の開始日未満まで指定します。例はDATE型を想定し、日付リテラルの構文は利用するDBMSに合わせます。
副問い合わせで平均と比べる
SELECT sale_id, amount
FROM sales
WHERE amount > (SELECT AVG(amount) FROM sales);
最初の4行の平均は650です。結果は900と700の2行になります。この形では比較に使う副問い合わせが1つの値を返す必要があります。複数行を返す検索と単純な等号比較を組み合わせると、エラーになる場合があります。
EXISTS・NOT EXISTSと相関副問い合わせ
SELECT c.customer_id, c.customer_name
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);
この例は顧客表customersと注文表ordersを想定しています。内側で外側のc.customer_idを参照するのが相関です。対応する注文が1行でもあればその顧客を残し、NOT EXISTSなら該当する注文がない顧客を残します。注文数が多くても、この存在条件だけで同じ顧客行が増えることはありません。
EXISTSは返された行の有無を判定します。SELECT 1はよく使う記法で、1という値自体を比較しているわけではありません。外側の行ごとに対応を考えると理解できますが、実際には最適化で別の実行方法が選ばれることもあります。INより必ず速いという保証はありません。
NOT INとNULLを慎重に扱う
通常の単一値比較では、5 NOT IN (1, NULL)は真にならず、WHEREではその行が残りません。NOT EXISTSは行の存在を判定しますが、内側の比較式にNULLがあれば、その比較は真にならないことがあります。NULLの行を一致として扱うかなど、求める結果を先に決めましょう。両者を機械的に置き換えるのは避けます。
確認問題
最初の売上表から「各売上が500以上」というWHEREだけを外し、店舗別合計1000以上をHAVINGで選ぶと、結果はどうなりますか?
解答・解説を見る
東店1500、西店1100の2行です。WHEREを外すと西店の400も集計対象になります。行を除く条件と、合計後にグループを除く条件は区別します。
基本構文は前章:SQL① 基本的なSELECT文から復習できます。
SQLをnoteの例題で復習する
基礎を確認したら、無料noteのSELECT・JOIN・GROUP BY・サブクエリの解説で、条件の読み取りとSQLの組み立てを復習できます。
集計する行と集計後のグループの違いに迷ったら、WHERE・GROUP BY・HAVINGを例題で比較するnoteへ進みましょう。
資格・目的別のnote教材ナビから、ほかの分野も選べます。
参考資料
PostgreSQL:FROM・WHERE・GROUP BY・HAVING / ORDER BY / 副問い合わせの条件式

コメント