構成比 — 全体の何%かを出す

中級143

カテゴリ別の売上構成比を出します。サブクエリで全体合計を持ってくる方法と、SUM() OVER で店舗ごとの分母に切り替える方法の 2 通りを練習します。

まずカテゴリ別に集計する — JOIN

daily_sales に商品カテゴリは入っていません。 products と結合して取ってきます。

SELECT p.category, SUM(ds.amount) AS sales
FROM daily_sales ds
JOIN products p ON p.id = ds.product_id
GROUP BY p.category
ORDER BY sales DESC;

daily_sales.amount単価 × 数量をあらかじめ入れてある列です。

そのため SUM(p.price * ds.quantity) と書いても同じ答えになります。

実務のテーブルでも、 集計を軽くするために金額を持たせておくことはよくあります。

割合にする — 分母をどう持ってくるか

「電子機器が 1451 万」 と言われてもピンときません。 全体の何%かに直します。

分母 (全体の合計) は 1 行だけの値なので、 スカラーサブクエリで取ってこられます。

SELECT p.category,
       SUM(ds.amount) AS sales,
       ROUND(SUM(ds.amount) * 100.0 / (SELECT SUM(amount) FROM daily_sales), 1) AS pct
FROM daily_sales ds
JOIN products p ON p.id = ds.product_id
GROUP BY p.category
ORDER BY sales DESC;

100.0 と小数で書くのが要点です。 100 と整数で書くと

整数どうしの割り算になって小数が切り捨てられ、 ほとんどが 0 になります

分母をグループごとに切り替える — SUM() OVER

「店舗ごとに、 その店の中での構成比」 が欲しいときは、 分母が店舗ごとに変わります。

サブクエリだと店舗の数だけ書き分けることになり、 現実的ではありません。

ここで 集計関数に OVER を付ける書き方が効きます。

SELECT ds.store, p.category,
       SUM(ds.amount) AS sales,
       ROUND(SUM(ds.amount) * 100.0
             / SUM(SUM(ds.amount)) OVER (PARTITION BY ds.store), 1) AS pct
FROM daily_sales ds
JOIN products p ON p.id = ds.product_id
GROUP BY ds.store, p.category
ORDER BY ds.store, sales DESC;

SUM(SUM(...)) OVER (...) という二重の SUM に驚くかもしれませんが、

順番に考えると素直です。

1. 内側の SUM(ds.amount) … GROUP BY で店舗×カテゴリの合計が出る (6 行になる)

2. 外側の SUM(...) OVER (PARTITION BY ds.store)その 6 行を店舗ごとに足す

ウィンドウ関数は GROUP BY の後に評価されるので、 集計済みの行に対して

さらに集計をかけられます。 この順番を覚えておくと、 二重 SUM は自然に読めます。

金額と数量では答えが逆になる

構成比を金額で見ると 文房具はわずか 3.6% です。 ところが数量で見ると、

いちばん売れているのはペンとノートです。

SELECT p.name, SUM(ds.quantity) AS q, SUM(ds.amount) AS sales
FROM daily_sales ds
JOIN products p ON p.id = ds.product_id
GROUP BY p.name
ORDER BY q DESC;

「売れている」 が金額なのか個数なのかで、 出す施策が変わります

構成比を出すときは、 何を分子に置いたのかを必ず列名に残しておきます。

よくあるつまずき

- pct が全部 0 になる100 を整数で書いています。 100.0 にします。

- 合計しても 100% にならない — 四捨五入の誤差です。 100.1% や 99.9% は正常で、

ぴったり合わせたい場合は最大の行で調整するのが一般的です。

- OVER の中に PARTITION BY を書き忘れる — 分母が全体になり、

「店舗ごとの構成比」 のつもりが 「全社の中での構成比」 になります。

実務での使いどころ

売上構成比は 「どこに手を入れるか」 を決めるための地図です。 店舗ごと ・ 月ごとに

同じ構成比を並べると、 全体の伸びではなく 中身の入れ替わりが見えます。

次のレッスン: 移動平均 — 日々のブレをならす

データベースを初期化中...
SQL エディタCtrl+Enter で実行
SQL を入力して実行してください
練習問題 — 0/3 完了 (0/90pt)
daily_sales と products を結合し、カテゴリ別の売上合計を出してください。列は category と sales、売上の多い順です。
25pt
カテゴリ別の売上に、全体に占める割合 pct (小数第 1 位まで) を足してください。列は category・sales・pct、売上の多い順です。
30pt
店舗ごとに、その店の中でのカテゴリ構成比を出してください。列は store・category・sales・pct、store 昇順 → sales 降順で並べます。
35pt