SQLのグループ集計(GROUP BY)と副問い合わせ(サブクエリ)を組み合わせると、平均以上の売上を持つ商品や、部門ごとの最大値を持つ従業員など、複雑な条件抽出が可能になります 。平均値などを事前に計算して WHERE 句で比較する用途で非常によく使われます。

画像参照:https://www.seplus.jp/dokushuzemi/blog/2019/03/beginner2pro_sqler.html
group by 〜 having句を使った集計
GROUP BY句でデータをグループ化し、HAVING句で集計結果(SUM, COUNT, AVGなど)に対する絞り込みを行う手法。WHERE句が集計前の行を絞り込むのに対し、HAVINGはグループ化後の集計値(例:合計100以上、件数5件以上)でフィルタリングする。
基本的な構文
sql
SELECT グループ化する列, 集計関数(列)
FROM テーブル名
[WHERE グループ化前の条件]
GROUP BY グループ化する列
HAVING 集計関数(列) 条件演算子 値;
具体的な使用例
例1: 合計金額の絞り込み
商品カテゴリー(category)ごとの合計売上金額(sales)を計算し、合計が1000円以上のカテゴリーのみを表示する。
sql
SELECT category, SUM(sales)
FROM orders
GROUP BY category
HAVING SUM(sales) >= 1000;
例2: 件数の絞り込み
クラス(class)ごとに生徒の人数をカウントし、人数が30人以上のクラスのみを表示する。
sql
SELECT class, COUNT(student_id)
FROM students
GROUP BY class
HAVING COUNT(student_id) >= 30;
例3: WHEREとHAVINGの併用
「2025年」のデータ(WHERE)から、店舗(shop)ごとの売上合計(SUM)を計算し、合計が10万円以上(HAVING)の店舗のみを抽出する。
sql
SELECT shop, SUM(amount)
FROM sales_table
WHERE sales_date >= '2025-01-01'
GROUP BY shop
HAVING SUM(amount) >= 100000;
ポイント
- 実行順序:
FROMWHEREGROUP BYHAVINGSELECTORDER BYの順に処理される。 - HAVINGの条件:
HAVINGには、GROUP BYで指定した項目か、SUMやCOUNTなどの集計関数を使用する必要がある。 - エイリアス:
SELECT句で付けた別名(AS)は、HAVING句内で使用できる場合とできない場合がある(DBMSによる)。
EXIST/NOT EXISTSと相関副問い合わせ
EXISTS/NOT EXISTSは、相関副問い合わせと組み合わせて、指定した条件を満たすデータが存在するか(またはしないか)をTRUE/FALSEで判定するSQLの強力な検索手法です。メインクエリの行ごとにサブクエリを評価し、存在チェックを行うため、INより効率的かつ、NULLの影響を受けにくいという特徴があります。
EXISTS/NOT EXISTSの概要
- EXISTS: サブクエリの結果が存在する場合(1行でも返される場合)に
TRUEを返し、メインクエリが結果を出力する。 - NOT EXISTS: サブクエリの結果が存在しない(0行)場合に
TRUEを返し、メインクエリが結果を出力する。 - データ構造: 通常、
WHERE句にて使用し、相関サブクエリの形式をとる。
相関副問い合わせとは
メインクエリ(外側)の1行ごとにサブクエリ(内側)が評価される構造のこと。
>>メインクエリとサブクエリについてはこちら
- 処理の流れ: メインテーブルのレコードを1つ取得
サブクエリの検索条件にその値を入れる
サブクエリを実行
結果を判定。
- 利点: データの存在チェックに特化しているため、サブクエリ内で具体的な値(
SELECT *やSELECT 1など)を返さなくてよい。
具体例:相関副問い合わせとEXISTS
「注文がある顧客」だけを取得する例。
sql
SELECT c.customer_name
FROM Customers c
WHERE EXISTS (
SELECT 1
FROM Orders o
WHERE o.customer_id = c.customer_id -- 相関部分(外側のc.idを参照)
);
Customersテーブルの各顧客に対し、Ordersテーブルに同じcustomer_idが存在するかを確認します。
NOT EXISTSの重要性(NULL対策)
NOT INはサブクエリの結果にNULLが含まれると結果が0件になるという落とし穴がありますが、NOT EXISTSはNULLが含まれていても正しく存在しないデータを取得できます。
EXISTSとINの使い分け
- IN: 具体的な値のリストと一致するデータを探す場合。
- EXISTS: 関連するテーブルにデータが存在するかという「有無」で判断する場合。一般的に、大きなテーブルを扱う場合、EXISTSの方がパフォーマンスが良い傾向があります。
まとめ
- EXISTS: データの「存在」をチェック。
- NOT EXISTS: データの「不存在」をチェック。
- 相関副問い合わせ: 外側の行ごとの評価。
- NULL対応:
NOT INよりNOT EXISTSが安全。

コメント