IPA|情報処理技術者試験

【SQL入門】GROUPING SETS, ROLLUP, CUBEの違いと使い方を徹底解説

SQLでデータを集計する際、GROUP BY句は非常に強力な武器です。しかし、「部署ごとの売上」「役職ごとの売上」「全社の総売上」といった複数の集計を一度に行いたい場合、どうしていますか? おそらく、それぞれの集計クエリを書いて UNION ALL で結合する、といった面倒な手順を踏んでいるのではないでしょうか。この方法ではSQLが複雑で長くなり、メンテナンス性も低下してしまいます。

実は、SQLにはこうした課題をスマートに解決するための強力な機能が備わっています。それが、GROUPING SETSROLLUPCUBE といった拡張GROUP BY句です。これらは「グループ化セット」とも呼ばれ、1つのクエリで複数パターンの集計を一度に取得できるため、データ分析やレポーティングの効率を劇的に向上させます。

この記事では、GROUPING SETSROLLUPCUBEの基本的な使い方から、それぞれの違い、そしてどのような場面で役立つのかまでを、具体的なサンプルデータとコード、図解を交えながら網羅的に解説します。データベーススペシャリスト試験などの資格対策はもちろん、実務でのデータ活用スキルを一段階レベルアップさせたい方も、ぜひ最後までご覧ください。

まずは基本から│GROUP BY句の課題とサンプルデータ

GROUPING SETSなどの高度な機能を見ていく前に、まずは基本となるGROUP BY句の役割と、複数の集計を行おうとした際の課題について簡単におさらいしましょう。

GROUP BY句と複数集計の課題

GROUP BYは、指定した列(例:部署名)の値が同じ行を一つのグループにまとめ、SUM()COUNT()といった集計関数を適用するための句です。しかし、例えば「①部署ごとの合計給与」と「②役職ごとの合計給与」を同時に見たい場合、一つのGROUP BY句でこれを表現することはできません。

従来の方法では、以下のようにそれぞれの集計クエリを書き、UNION ALLで結合する必要がありました。

UNION ALLを使った複数パターンの集計例】


-- ① 部署ごとの合計給与
SELECT
  department,
  NULL AS position,
  SUM(salary) AS total_salary
FROM
  employees
GROUP BY
  department

UNION ALL

-- ② 役職ごとの合計給与
SELECT
  NULL AS department,
  position,
  SUM(salary) AS total_salary
FROM
  employees
GROUP BY
  position;

この方法でも結果は得られますが、クエリが冗長になり、集計パターンが増えるほどSQLは複雑化していきます。この課題を解決するのが、これから学ぶグループ化セットです。

今回使用するサンプルデータ

この記事では、以下のような「従業員(employees)」テーブルを例に解説を進めます。部署(department)、役職(position)、性別(gender)、給与(salary)といったカラムを持つシンプルなテーブルです。

【employees テーブル】

id department position gender salary
1 営業部 部長 男性 800
2 営業部 課長 女性 600
3 営業部 一般 男性 400
4 営業部 一般 女性 400
5 開発部 部長 男性 850
6 開発部 課長 男性 650
7 開発部 一般 女性 450
8 人事部 課長 女性 580
9 人事部 一般 男性 380

このデータを元に、GROUPING SETSROLLUPCUBEがどのように動作するのかを見ていきましょう。


GROUPING SETS句のSQL│指定した組み合わせを一度に集計

UNION ALLの冗長さを解消する最初の切り札がGROUPING SETSです。これは、集計したいグループの組み合わせを括弧 () で自由に指定できる機能です。まるでレストランでアラカルトメニューを注文するように、欲しい集計パターンだけをピンポイントで要求できます。

基本的な使い方とSQL構文

GROUPING SETSGROUP BY句の中で使用します。基本的な構文は以下の通りです。


SELECT
  column1,
  column2,
  集計関数(column3)
FROM
  table_name
GROUP BY
  GROUPING SETS ( (column1), (column2), ... );

先ほどのUNION ALLで実現した「①部署ごとの合計給与」と「②役職ごとの合計給与」は、GROUPING SETSを使えば次の一つのSQLで実現できます。

【GROUPING SETS を使ったSQL例】


SELECT
  department,
  position,
  SUM(salary) AS total_salary
FROM
  employees
GROUP BY
  GROUPING SETS ( (department), (position) );

実行結果とNULLの意味

上記のSQLを実行すると、結果は以下のようになります。UNION ALLを使った時と似た結果が、よりシンプルなクエリで得られました。

department position total_salary
営業部 NULL 2200
開発部 NULL 1950
人事部 NULL 960
NULL 部長 1650
NULL 課長 1830
NULL 一般 1630

ここで注目すべきはNULLの存在です。
このNULLは、データが元々NULLであるという意味ではなく、「この行はその列でグループ化されていませんよ」ということを示す特別なNULLです。例えば、departmentが「営業部」でpositionNULLの行は、「部署ごとに集計した結果」であり、役職は考慮していないことを意味します。

複数列や総計の組み合わせも可能

GROUPING SETSの強力な点は、複数列の組み合わせや、全データを対象とした総計(グランドトータル)も指定できることです。

  • (department, position):部署と役職の組み合わせで集計
  • ():全データを1つのグループとして集計(総計)

例えば、「部署ごと」「役職ごと」「部署と役職の組み合わせごと」「全体の合計」の4パターンを一度に取得したい場合は、以下のように記述します。


SELECT
  department,
  position,
  SUM(salary) AS total_salary
FROM
  employees
GROUP BY
  GROUPING SETS ( (department), (position), (department, position), () );

このようにGROUPING SETSは、開発者が必要とする集計の組み合わせを柔軟かつ明示的に指定できる、非常に便利な機能です。

ROLLUPの使い方│階層的な小計・合計を自動生成するSQL

GROUPING SETSがアラカルトだとしたら、ROLLUPコース料理のように決まったパターンの集計を自動的に行ってくれる機能です。特に、日次→月次→年次のような階層構造を持つデータの集計(ドリルダウン分析)で真価を発揮します。

ROLLUPは、指定された列の組み合わせを、右側の列から一つずつ取り除きながら集計パターンを生成します。

基本的な使い方とSQL構文

ROLLUP(department, position)と指定した場合、内部的には以下の3つの集計パターンを生成するGROUPING SETSと等価になります。

  1. (department, position) :部署と役職ごとの集計(最も詳細)
  2. (department) :部署ごとの小計
  3. () :全体の合計(グランドトータル)

【ROLLUP を使ったSQL例】


SELECT
  department,
  position,
  SUM(salary) AS total_salary
FROM
  employees
GROUP BY
  ROLLUP (department, position);

実行結果とGROUPING SETSとの違い

上記のSQLを実行すると、結果は以下のようになります。

department position total_salary
営業部 部長 800
営業部 課長 600
営業部 一般 800
営業部 NULL 2200
開発部 部長 850
開発部 課長 650
開発部 一般 450
開発部 NULL 1950
人事部 課長 580
人事部 一般 380
人事部 NULL 960
NULL NULL 5110

GROUPING SETSの例と見比べると違いは明らかです。ROLLUP(department, position)の詳細な集計に加えて、部署ごとの小計positionNULLの行)と、全体の合計departmentpositionが両方NULLの行)を自動的に追加してくれています。

ROLLUPは指定された列の階層関係を意識し、「詳細→中項目→大項目」へと巻き上げて集計(ロールアップ)してくれるのです。これにより、集計パターンを一つずつ記述する手間が省け、コードもシンプルになります。


CUBEの使い方│全パターンのクロス集計を網羅するSQL

ROLLUPが階層的な集計を得意とする一方、CUBE指定された列の考えられるすべての組み合わせを網羅的に集計します。階層関係を意識せず、サイコロ(キューブ)をあらゆる角度から眺めるように、多角的なクロス集計を行いたい場合に最適です。

ROLLUPとの違い

CUBEROLLUPの最も大きな違いは、集計パターンの生成方法にあります。
CUBE(department, position)と指定した場合、内部的には以下の4つの全組み合わせを生成するGROUPING SETSと等価になります。

  1. (department, position):部署と役職ごとの集計
  2. (department):部署ごとの小計
  3. (position):役職ごとの小計 ← ROLLUPには無かったパターン
  4. ():全体の合計

ROLLUPが指定した順序に沿って階層的に集計するのに対し、CUBEは順序を考慮せず、あらゆるパターンの集計結果を出力します。

基本的な使い方とSQL構文

【CUBE を使ったSQL例】


SELECT
  department,
  position,
  SUM(salary) AS total_salary
FROM
  employees
GROUP BY
  CUBE (department, position);

実行結果と考察

上記のSQLを実行すると、結果は以下のようになります。ROLLUPの結果に加えて、departmentNULLの「役職ごと」の集計行が追加されている点に注目してください。

department position total_salary
営業部 部長 800
営業部 課長 600
営業部 一般 800
営業部 NULL 2200
開発部 部長 850
開発部 課長 650
開発部 一般 450
開発部 NULL 1950
人事部 課長 580
人事部 一般 380
人事部 NULL 960
NULL 部長 1650
NULL 課長 1830
NULL 一般 1630
NULL NULL 5110

このようにCUBEを使えば、「部署ごとの特徴」と「役職ごとの特徴」という異なる軸の分析を一度のクエリで実行できます。ただし、集計対象の列が増えると組み合わせの数が爆発的に増加($2^n$通り)するため、パフォーマンスへの影響を考慮して使用する必要があります。

3つの違いを比較│GROUPING SETS・ROLLUP・CUBEの使い分け

ここまで解説してきた3つの機能を、改めて比較して整理しましょう。それぞれの特徴を理解し、目的の集計に最も適したものを選択することが、効率的なデータ分析の鍵となります。

機能比較一覧表

機能 特徴 イメージ こんなときにおすすめ
GROUPING SETS 必要な集計パターンを 自由に、明示的に 指定する。 アラカルト(単品注文) ・決まったパターンのレポート作成
・階層や網羅性が必要ない特定の集計
ROLLUP 指定した列の 階層に従って 小計・合計を自動生成する。 コース料理 ・日次→月次→年次レポート
・国→都道府県→市区町村の売上集計
CUBE 指定した列の すべての組み合わせ を網羅的に集計する。 ビュッフェ(全種類) ・多角的なクロス集計
・データ探索や分析の初期段階

GROUPING関数で集計行を分かりやすく

GROUPING SETSROLLUPCUBEを使うと、集計行にはNULLが表示されます。しかし、元のデータがNULLだった場合と区別がつきません。そこで役立つのがGROUPING関数です。

GROUPING(列名)は、その行が指定した列で集計された結果(NULLが表示されている行)であれば1を、そうでなければ0を返します。

GROUPING関数を使ったSQL例】


SELECT
  GROUPING(department) AS is_dept_total,
  GROUPING(position) AS is_pos_total,
  department,
  position,
  SUM(salary) AS total_salary
FROM
  employees
GROUP BY
  CUBE (department, position)
ORDER BY
  department, position;

このクエリを実行すると、どの列が集計対象になっているかが01で明確に判別できるようになり、アプリケーションでの処理や分析がより容易になります。例えばis_dept_total1の行は、部署の垣根を越えた集計(役職ごとの集計や総計)であることを示します。

-IPA|情報処理技術者試験