曜日別集計 — 合計ではなく平均で比べる

中級133

曜日ごとの売れ方を出します。曜日番号を CASE で日本語に直し、日数が違うものを比べるときに合計ではなく 1 日あたりで見る理由を練習します。

曜日を取り出す — strftime('%w')

%w は曜日を 0 (日曜) 〜 6 (土曜) の数字で返します。

SELECT sale_date, strftime('%w', sale_date) AS w FROM daily_sales LIMIT 7;

返ってくるのは数字ではなく '0' という文字列です。 比較するときは

strftime('%w', sale_date) = '0' とクォートを付けます。 付け忘れても

SQLite は暗黙に変換してくれますが、 他のデータベースでは型エラーになります。

数字を曜日名に直す — CASE

w = 3 と言われて水曜だと分かる人はいません。 人が読む列にするのが

レポートの仕事です。

SELECT CASE strftime('%w', sale_date)
         WHEN '0' THEN '日'
         WHEN '1' THEN '月'
         WHEN '2' THEN '火'
         WHEN '3' THEN '水'
         WHEN '4' THEN '木'
         WHEN '5' THEN '金'
         ELSE '土'
       END AS weekday,
       SUM(amount) AS sales
FROM daily_sales
GROUP BY strftime('%w', sale_date)
ORDER BY sales DESC;

CASE 式 WHEN 値 THEN ... という形は 1 つの式を複数の値と突き合わせる書き方です。

条件が複雑なときは CASE WHEN 条件 THEN ... (式を書かない形) を使います。

GROUP BY は CASE の結果ではなく元の %w で行うのがポイントです。

表示は日本語、 グループ分けは数字、 と役割を分けておくと、 曜日順に並べたいときに

ORDER BY strftime('%w', sale_date) がそのまま使えます。

合計で比べると嘘になる

曜日別の合計を並べると、 その曜日が期間内に何回あったかで差が付きます。

90 日の中に水曜は 12 回、 他の曜日は 13 回ずつあります。 1 回ぶん少ないだけで

水曜は不利です。

比べるなら 1 日あたりに直します。

SELECT strftime('%w', sale_date) AS w,
       SUM(amount) AS sales,
       COUNT(DISTINCT sale_date) AS days,
       ROUND(SUM(amount) * 1.0 / COUNT(DISTINCT sale_date)) AS per_day
FROM daily_sales
GROUP BY w
ORDER BY per_day DESC;

* 1.0 を掛けているのは、 整数どうしの割り算が小数を切り捨てるからです。

これを忘れると 「1 日あたり 32 万」 が 「32 万」 ではなく妙な値になります。

平日と週末をまとめる

粒度は 7 つでなくても構いません。 CASE WHEN で 2 つに畳むと傾向がはっきりします。

SELECT CASE WHEN strftime('%w', sale_date) IN ('0','6') THEN '週末' ELSE '平日' END AS kind,
       ROUND(SUM(amount) * 1.0 / COUNT(DISTINCT sale_date)) AS per_day
FROM daily_sales
GROUP BY kind;

このデータでは 週末が 1 日あたり約 30 万、 平日が約 24 万で、

週末は平日の 1.28 倍と分かります。

よくあるつまずき

- 曜日の数字と名前がずれる%w0 が日曜です。 月曜始まりだと思って

ずらすと 1 つずつ間違えます。 迷ったら SELECT sale_date, strftime('%w', sale_date)

を実際に見て確かめます。

- ELSE を書き忘れる — CASE に当てはまらない行は NULL になり、

GROUP BY で 「名前のないグループ」 ができます。

- 合計だけ見て 「水曜は弱い」 と結論する — 回数が違うだけかもしれません。

必ず COUNT(DISTINCT sale_date) を並べて確かめます。

実務での使いどころ

シフトの人数、 広告の配信曜日、 セールの設定日 — 曜日別の売れ方は

そのまま運用の判断に変わります。 「合計ではなく 1 日あたりで見る」 は

店舗比較でも期間比較でも同じように効く考え方です。

次のレッスン: 構成比 — 全体の何%かを出す

データベースを初期化中...
SQL エディタCtrl+Enter で実行
SQL を入力して実行してください
練習問題 — 0/3 完了 (0/85pt)
曜日番号ごとの売上合計を出してください。列は w (0〜6 の文字列) と sales、w の昇順で並べます。
25pt
曜日を日本語 1 文字 (日・月・火・水・木・金・土) にして売上合計を出してください。列は weekday と sales、売上の多い順に並べます。
30pt
週末 (日・土) と平日に分けて、1 日あたりの売上 per_day を出してください。列は kind と per_day、per_day の多い順です。小数は ROUND で丸めます。
30pt