[SQLのはじめ方] Part10: GROUP BY と HAVING句の使い方

データをグループ化して、さらに絞り込む方法をマスターしよう!

前回は COUNTSUM などの集計関数を学びましたね。今回は、それらの集計関数と組み合わせて使うことで、SQLの分析能力を格段に向上させる GROUP BY 句と HAVING 句について解説します。これらを使いこなせば、より複雑なデータ集計や分析が可能になります

GROUP BY句: データをグループにまとめる

GROUP BY 句は、テーブル内のデータを特定のカラムの値に基づいてグループ化するための機能です。同じ値を持つ行がひとつのグループにまとめられます。そして、各グループに対して集計関数(COUNT, SUM, AVG など)を適用できます。

例えば、以下のような「社員」テーブル (employees) があるとします。

employee_id name department salary
1 山田太郎 営業部 300000
2 佐藤花子 開発部 350000
3 鈴木一郎 営業部 320000
4 高橋美咲 人事部 280000
5 田中健太 開発部 400000
6 渡辺直美 営業部 290000

このテーブルから、部署 (department) ごとの社員数を知りたい場合、GROUP BY 句を使って次のように書けます。

SELECT
  department,
  COUNT(*) AS employee_count -- 各部署の行数を数える (社員数)
FROM
  employees
GROUP BY
  department; -- department カラムの値でグループ化

このクエリを実行すると、部署ごとに社員数が集計された結果が得られます。

department employee_count
営業部 3
開発部 2
人事部 1

同様に、部署ごとの平均給与を計算することもできます。

SELECT
  department,
  AVG(salary) AS average_salary -- 各部署の平均給与を計算
FROM
  employees
GROUP BY
  department; -- department カラムの値でグループ化

GROUP BY のポイント

SELECT 句には、GROUP BY で指定したカラム(グループ化のキー)と集計関数のみを含めるのが基本です。他のカラムを含めると、どの行の値を表示すべきかデータベースが判断できず、エラーになるか、意図しない結果になることがあります。(一部のデータベースでは挙動が異なる場合がありますが、標準SQLではこのルールに従うのが安全です。)

HAVING句: グループ化された結果に条件を適用する

GROUP BY でグループ化した結果に対して、さらに条件を指定して絞り込みたい場合があります。例えば、「社員数が2人以上の部署だけを表示したい」といったケースです。

ここで HAVING 句の出番です! HAVING 句は、GROUP BY によって作成されたグループに対して条件を指定するためのものです。

WHERE句との違い

条件を指定する句としては WHERE 句もありましたね。HAVING 句と WHERE 句の主な違いは、条件を適用するタイミングです。

  • WHERE 句: グループ化される前の個々の行に対して条件を適用します。集計関数に対する条件は指定できません。
  • HAVING 句: グループ化された後のグループに対して条件を適用します。集計関数の結果に対する条件を指定できます。

先ほどの例で、「社員数が2人以上の部署」を抽出するには、次のように HAVING 句を使います。

SELECT
  department,
  COUNT(*) AS employee_count
FROM
  employees
GROUP BY
  department
HAVING
  COUNT(*) >= 2; -- グループ化後の結果 (社員数) が2以上のものだけを抽出

このクエリを実行すると、以下の結果が得られます。

department employee_count
営業部 3
開発部 2

人事部は社員数が1人なので、HAVING 句の条件 (COUNT(*) >= 2) を満たさず、結果から除外されました。

同様に、「平均給与が30万円を超える部署」を抽出することもできます。

SELECT
  department,
  AVG(salary) AS average_salary
FROM
  employees
GROUP BY
  department
HAVING
  AVG(salary) > 300000; -- グループ化後の結果 (平均給与) が300000より大きいものだけを抽出

HAVING の注意点

HAVING 句は通常 GROUP BY 句と一緒に使われます。HAVING 句の条件式には、GROUP BY で指定したカラム、集計関数、または定数などを含めることができます。

WHERE句とHAVING句の組み合わせ

WHERE 句と HAVING 句は、ひとつのクエリ内で一緒に使うこともできます。これにより、まず個々の行をフィルタリングし、その後でグループ化された結果をさらにフィルタリングするという、より複雑な条件指定が可能です。

例えば、「給与が30万円以上の社員に限定し、その中で部署ごとの人数を計算し、その人数が2人以上の部署のみを表示する」場合、次のように書けます。

SELECT
  department,
  COUNT(*) AS employee_count
FROM
  employees
WHERE
  salary >= 300000 -- まず個々の行を絞り込む (給与30万以上)
GROUP BY
  department       -- 残った行を部署でグループ化
HAVING
  COUNT(*) >= 2;    -- グループ化後の結果 (社員数) が2以上のものだけを抽出

このクエリの処理順序は以下のようになります。

  1. FROM employees: `employees` テーブルからデータを読み込む。
  2. WHERE salary >= 300000: 給与が30万円未満の行を除外する。
  3. GROUP BY department: 残った行を `department` カラムの値でグループ化する。
  4. HAVING COUNT(*) >= 2: 各グループの行数 (社員数) を計算し、2未満のグループを除外する。
  5. SELECT department, COUNT(*) AS employee_count: 最終的に残ったグループの `department` と計算された `employee_count` を表示する。

(実際のSQLの内部的な実行計画はより複雑な場合がありますが、概念的な順序としてこのように理解すると分かりやすいでしょう。)

SQL句の基本的な評価順序

一般的に、SQLクエリの各句は以下の順序で評価されると考えられます。
FROMWHEREGROUP BYHAVINGSELECTORDER BYLIMIT/ OFFSET
この順序を意識すると、WHERE で集計関数が使えない理由や、HAVING の役割が理解しやすくなります。

まとめ

今回は、データをグループ化して集計するための GROUP BY 句と、そのグループ化された結果に条件を適用する HAVING 句について学びました。

  • GROUP BY: 特定のカラムの値に基づいて行をグループ化し、集計関数を適用する。
  • HAVING: GROUP BY でグループ化された結果に対して、集計結果を用いた条件を指定する。
  • WHERE はグループ化の行に、HAVING はグループ化のグループに条件を適用する。

これらの句を使いこなすことで、データの集計や分析の幅が大きく広がります。色々な条件で試してみて、その動作をしっかり理解しましょう! 次回は NULL の扱い方について学びます。お楽しみに!

参考情報

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です