スポンサーリンク

【応用情報技術者試験】データベースを学ぼう!     ~第5章~SQL② グループ集計、副問い合わせ

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;

ポイント

  • 実行順序FROM  WHERE  GROUP BY  HAVING  SELECT  ORDER BY の順に処理される。
  • HAVINGの条件HAVINGには、GROUP BYで指定した項目か、SUMCOUNTなどの集計関数を使用する必要がある。
  • エイリアス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 EXISTSNULLが含まれていても正しく存在しないデータを取得できます。 

EXISTSとINの使い分け

  • IN: 具体的な値のリストと一致するデータを探す場合。
  • EXISTS: 関連するテーブルにデータが存在するかという「有無」で判断する場合。一般的に、大きなテーブルを扱う場合、EXISTSの方がパフォーマンスが良い傾向があります。 

まとめ

  • EXISTS: データの「存在」をチェック。
  • NOT EXISTS: データの「不存在」をチェック。
  • 相関副問い合わせ: 外側の行ごとの評価。
  • NULL対応NOT INよりNOT EXISTSが安全。 

コメント