GROUP BY: カテゴリ別に集計する
Stage 2 — 第2章 | データ分析基礎カリキュラム 推定学習時間:35〜45分 | 難易度:★★☆☆☆
この章で学ぶこと
前章では、COUNT や SUM を使って、テーブル全体から1つの指標を作りました。
しかし実務の分析では、全体の数字だけでは足りないことがよくあります。
たとえば、ECサイトで次のような問いに答えるには、カテゴリ別・地域別・ステータス別に集計する必要があります。
- 商品カテゴリごとの売上はいくらか
- 都道府県ごとの顧客数は何人か
- 注文ステータスごとの件数はどう分かれているか
- 顧客ごとの購入回数は何回か
この章では、カテゴリ別に集計するための GROUP BY を学びます。
この章を終えると、こんなことができるようになります:
GROUP BYでカテゴリ別の集計表を作れる- 集計単位と行の粒度を説明できる
COUNT,SUM,AVGとGROUP BYを組み合わせられる- カテゴリ別の比較から分析の問いを作れる
1. GROUP BYは「同じ値ごとにまとめる」
GROUP BY は、指定した列の値が同じ行を1つのグループにまとめます。
そのうえで、各グループごとに集計関数を計算します。
たとえば、注文ステータスごとの件数を数えるSQLです。
SELECT
status,
COUNT(*) AS order_count
FROM orders
GROUP BY status;
このSQLは、completed, cancelled, pending などのステータスごとに注文件数を数えます。
| status | order_count |
|---|---|
| completed | 1200 |
| cancelled | 80 |
| pending | 35 |
全体の COUNT(*) は1つの値を返します。
GROUP BY status を追加すると、ステータスごとの複数行の集計結果になります。
2. GROUP BYの基本形
GROUP BY は、集計したい単位の列を指定します。
SELECT
集計したい列,
集計関数
FROM テーブル名
GROUP BY 集計したい列;
商品カテゴリごとの商品数を数える例です。
SELECT
category,
COUNT(*) AS product_count
FROM products
GROUP BY category;
このSQLでは、category が同じ商品を1つのグループにまとめ、カテゴリごとの商品数を数えます。
SELECT に表示する通常の列は、原則として GROUP BY にも書くと考えましょう。
集計結果の1行が何を表しているのかを明確にするためです。
3. カテゴリ別の売上を出す
カテゴリ別売上を見るには、注文、注文明細、商品を結びつけてから集計します。
ここでは order_items と products を使います。
SELECT
p.category,
SUM(oi.quantity * oi.unit_price) AS sales
FROM order_items AS oi
JOIN products AS p
ON oi.product_id = p.product_id
GROUP BY p.category;
このSQLは、商品カテゴリごとに販売金額を合計します。
quantity * unit_price は、明細1行の売上金額です。
実務では、「何を合計しているか」を必ず確認します。
orders.total_amount を使うのか、order_items.quantity * unit_price を使うのかで、分析の粒度が変わります。
4. ORDER BYで大きい順に見る
カテゴリ別売上は、金額が大きい順に並べると解釈しやすくなります。
SELECT
p.category,
SUM(oi.quantity * oi.unit_price) AS sales
FROM order_items AS oi
JOIN products AS p
ON oi.product_id = p.product_id
GROUP BY p.category
ORDER BY sales DESC;
ORDER BY sales DESC によって、売上が大きいカテゴリから順に表示されます。
集計表は、並び替えとセットで使うと発見が増えます。 上位カテゴリを見ることで、売上の中心になっている商品群を把握できます。
5. 複数列でグループ化する
GROUP BY には複数の列を指定できます。
たとえば、都道府県と注文ステータスの組み合わせごとに注文件数を数えます。
SELECT
c.prefecture,
o.status,
COUNT(*) AS order_count
FROM orders AS o
JOIN customers AS c
ON o.customer_id = c.customer_id
GROUP BY
c.prefecture,
o.status
ORDER BY
c.prefecture,
o.status;
このSQLの1行は、「ある都道府県の、あるステータスの注文数」を表します。
複数列の GROUP BY は、選んだ列の組み合わせごとに集計するという意味です。
Stage 1で学んだ複数列の DISTINCT と似た考え方です。
6. 集計単位を言葉で説明する
GROUP BY で重要なのは、集計結果の1行が何を表すかです。
| SQL | 集計結果の1行が表すもの |
|---|---|
GROUP BY status |
1つの注文ステータス |
GROUP BY category |
1つの商品カテゴリ |
GROUP BY customer_id |
1人の顧客 |
GROUP BY prefecture, status |
1つの都道府県とステータスの組み合わせ |
たとえば、顧客ごとの購入回数を出すSQLです。
SELECT
customer_id,
COUNT(*) AS order_count,
SUM(total_amount) AS total_sales
FROM orders
WHERE status = 'completed'
GROUP BY customer_id;
この結果の1行は「1人の顧客」を表します。 顧客ごとの購入回数や累計購入金額を見たいときに使います。
7. よくあるミス
GROUP BYしない列をSELECTに入れる
次のSQLは、集計単位が曖昧です。
SELECT
status,
order_date,
COUNT(*) AS order_count
FROM orders
GROUP BY status;
status ごとにまとめているのに、どの order_date を表示すればよいか決まりません。
日付も含めて集計したいなら、GROUP BY に追加します。
SELECT
order_date,
status,
COUNT(*) AS order_count
FROM orders
GROUP BY
order_date,
status;
集計前の行と集計後の行を混同する
GROUP BY customer_id の結果は、注文1件ごとの表ではありません。
顧客1人ごとの集計表です。
行の意味が変わることを意識しましょう。
実務での使いどころ: 比較できる単位にそろえる
GROUP BYは、全体の数字をカテゴリ別・日別・顧客別などの比較できる単位に分けるために使います。 「売上が下がった」という全体の数字だけでは、どこで下がったのか分かりません。
SELECT
p.category,
SUM(oi.quantity * oi.unit_price) AS sales
FROM order_items AS oi
JOIN products AS p
ON oi.product_id = p.product_id
GROUP BY p.category
ORDER BY sales DESC;
このSQLはカテゴリ別売上を出します。 GROUP BYを使うときは、結果の1行が何を表すかを必ず言葉で説明します。
| GROUP BYする列 | 結果の1行 |
|---|---|
category |
商品カテゴリ1つ |
prefecture |
都道府県1つ |
customer_id |
顧客1人 |
DATE_TRUNC('month', order_date) |
月1つ |
GROUP BYは、分析の粒度を決める構文です。 粒度を間違えると、正しいSQLでも意思決定に使いにくい表になります。
ミニ演習
次の分析では、何でGROUP BYすべきか考えてください。
- 都道府県別の顧客数を見たい。
- 商品カテゴリ別の売上を見たい。
- 月別の注文件数を見たい。
- 顧客ごとの購入回数を見たい。
まとめ
| 構文 | 意味 | 例 |
|---|---|---|
GROUP BY |
同じ値ごとに行をまとめる | GROUP BY category |
| 集計関数との併用 | グループごとに指標を出す | SUM(total_amount) |
複数列の GROUP BY |
列の組み合わせでまとめる | GROUP BY prefecture, status |
ORDER BY との併用 |
集計結果を見やすく並べる | ORDER BY sales DESC |
この章のキーメッセージ:
GROUP BY は、全体の数字をカテゴリ別・顧客別・地域別の比較に変えるための基本です。集計結果の1行が何を表すのかを、必ず言葉で説明できるようにしましょう。
この章の確認
GROUP BY statusは、どのような単位で行をまとめますか?- 商品カテゴリごとの商品数を数えるSQLを書いてください。
- 顧客ごとの完了注文件数を出すSQLを書いてください。
- 複数列で
GROUP BYするとき、集計結果の1行は何を表しますか?