SQLite | ゼロからはじめるSQL、30日で習得するSQLite:実践 - Day30 アウトプット

SQL SQLite
スポンサーリンク

Day30 前半のゴール

「“SQLだけでレポートを作る”感覚と、“他人に説明する”視点を手に入れる」

ここまで29日間、
テーブル設計・JOIN・集計・インデックス・EC風DB設計まで、一通りやってきました。

Day30 のテーマはアウトプットです。

SQLだけで、シンプルなレポートを組み立てる
そのレポートが「何を前提に、何を示しているか」を他人に説明できる

前半では、特にこの2つを狙います。

「SQLを書ける」から一歩進んで、
「SQLで“意味のあるレポート”を作れる人」になるためのラストスパートです。


レポートとは何か

「“数字の一覧”ではなく、“問いに対する答え”」

まず、「レポートって何?」を言葉で整理します。

レポートは、単なる数字の羅列ではありません。
一言で言うと、

ある問いに対して、
前提を決めて、
数字で答えを返すもの

です。

例えば、EC風の世界なら、こんな問いがあります。

今月、どの商品がどれくらい売れているか
どのユーザーがよく買っているか
日別の売上推移はどうなっているか
キャンセル率はどれくらいか

レポートは、こうした問いに対して、

対象期間はどこからどこまでか
キャンセルは含めるか
税や送料は含めるか
単位は「件」なのか「金額」なのか

といった前提を決めたうえで、
SQLで数字を出し、それを人間が読める形に並べたものです。

ここで重要なのは、

SQLを書く前に、「何を知りたいのか」をはっきりさせる

という姿勢です。


Day29 の EC 風DBを“レポートの材料”として見る

「テーブルは“レポートの素材置き場”」

Day29 で作った EC 風のテーブルを、レポートの視点で見直してみます。

users
誰が、いつ登録したか、どんなステータスか

products
何を、いくらで売っているか、今売っているか

orders
誰が、いつ、いくらの注文をしたか
支払い状況・配送先・ステータス

order_items
どの注文で、どの商品を、いくらで、何個売ったか

この時点で、すでにかなりのレポートが作れます。

ユーザー別売上
商品別売上
日別売上
支払い方法別売上
ステータス別件数(キャンセル率など)

つまり、
テーブル設計がしっかりしていれば、
レポートは「JOIN+集計の組み合わせ」でいくらでも作れる、ということです。


レポート1:商品別売上ランキング

「“前提を言葉にしてから”SQLを書く」

最初のレポートとして、商品別売上ランキングを作ります。

まず、問いと前提を言葉にします。

問い
「直近1か月で、どの商品がいくら売れたかを知りたい」

前提
対象期間:2025-05-01〜2025-05-31
キャンセルされた注文は除外する(status <> 3)
売上は「単価×数量」の合計
ランキングは売上金額の降順

この「前提を言葉にする」ステップが、Day30 では特に重要です。
他人に説明するとき、この部分がそのまま口から出てきます。

では、SQLに落とします。

SELECT
  oi.product_id,
  oi.product_name,
  SUM(oi.unit_price * oi.quantity) AS total_amount,
  SUM(oi.quantity)                 AS total_quantity
FROM order_items oi
JOIN orders o
  ON oi.order_id = o.id
WHERE
  o.status <> 3
  AND o.ordered_at >= '2025-05-01 00:00:00'
  AND o.ordered_at <  '2025-06-01 00:00:00'
GROUP BY
  oi.product_id,
  oi.product_name
ORDER BY
  total_amount DESC;
SQL

このクエリを他人に説明するときは、こう言えれば十分です。

「2025年5月中の、キャンセル以外の注文を対象にして、
 商品ごとに単価×数量を合計し、売上金額の多い順に並べたレポートです。」

SQLの細かい文法ではなく、
「何を前提に、何を出しているか」を日本語で言えることが大事です。


レポート2:ユーザー別売上と購入回数

「“1人あたり”という視点をSQLに落とす」

次に、「どのユーザーがよく買っているか」を見るレポートを作ります。

問い
「直近3か月で、ユーザーごとの売上と購入回数を知りたい」

前提
対象期間:2025-03-01〜2025-05-31
キャンセルされた注文は除外
売上は注文ごとの total_amount の合計
購入回数は「注文の件数」

SQLはこうなります。

SELECT
  u.id   AS user_id,
  u.name AS user_name,
  COUNT(o.id)                      AS order_count,
  SUM(o.total_amount)              AS total_amount
FROM users u
JOIN orders o
  ON u.id = o.user_id
WHERE
  o.status <> 3
  AND o.ordered_at >= '2025-03-01 00:00:00'
  AND o.ordered_at <  '2025-06-01 00:00:00'
GROUP BY
  u.id,
  u.name
ORDER BY
  total_amount DESC;
SQL

説明するときは、こうです。

「2025年3月〜5月の間に、キャンセル以外の注文をしたユーザーについて、
 注文回数と売上合計をユーザー単位で集計し、売上の多い順に並べたレポートです。」

ここでのポイントは、

「1行が何を表しているか」を言えること
(この場合は「1ユーザー」)

「各カラムが何を意味しているか」を言えること
(order_count は注文件数、total_amount は売上合計)

です。


レポート3:日別売上と注文数の推移

「“時間の流れ”をレポートにする」

次は、「日別の売上と注文数」を見るレポートです。

問い
「直近1か月の、日別の売上と注文数の推移を知りたい」

前提
対象期間:2025-05-01〜2025-05-31
キャンセルされた注文は除外
売上は注文明細ベース(unit_price×quantity の合計)
注文数は「その日にあった注文の件数」

SQLはこう書けます。

SELECT
  date(o.ordered_at) AS order_date,
  COUNT(DISTINCT o.id) AS order_count,
  SUM(oi.unit_price * oi.quantity) AS total_amount
FROM orders o
JOIN order_items oi
  ON o.id = oi.order_id
WHERE
  o.status <> 3
  AND o.ordered_at >= '2025-05-01 00:00:00'
  AND o.ordered_at <  '2025-06-01 00:00:00'
GROUP BY
  date(o.ordered_at)
ORDER BY
  order_date;
SQL

説明はこうです。

「2025年5月中の、キャンセル以外の注文を対象にして、
 日付ごとに注文件数と売上合計を集計したレポートです。」

ここでのポイントは、

COUNT(DISTINCT o.id) で「注文の件数」を数えていること
SUM(oi.unit_price * oi.quantity) で「売上金額」を出していること
date(o.ordered_at) を GROUP BY のキーにしていること

を、自分の言葉で説明できるかどうかです。


「SQLだけでレポート作成」の本質

「“前提を決めて、1行の意味を定義する”作業」

ここまで3つのレポートを見てきましたが、
どれもやっていることは同じです。

対象となるテーブルを決める(FROM〜JOIN)
対象期間・対象ステータスなどの前提を決める(WHERE)
1行が何を表すかを決める(GROUP BY)
その1行ごとに、どんな数字を出すかを決める(SELECT+集計関数)

つまり、

SQLだけでレポートを作る
=「前提」と「1行の意味」を、SQLで定義する

ということです。

この感覚がつかめると、
新しいレポートを頼まれたときに、

「それは、何を1行として見たいレポートですか?」
「期間やキャンセルの扱いはどうしますか?」

と、自然に質問できるようになります。
これは、現場でめちゃくちゃ重宝されるスキルです。


他人に説明できる状態とは何か

「SQLを読むのではなく、“日本語で要約できる”こと」

Day30 のもう一つのテーマが、「他人に説明できる状態」です。

他人に説明できる、というのは、

SQLの全文を読み上げられること
ではなく
「このSQLは、こういう前提で、こういう単位で、こういう数字を出しています」
と日本語で言えること

です。

例えば、さっきのユーザー別売上のSQLを見て、

「ユーザーと注文をJOINして、
 2025年3〜5月のキャンセル以外の注文を対象に、
 ユーザーごとに注文件数と売上合計を出して、
 売上の多い順に並べている」

と説明できれば、それで十分です。

逆に言うと、
SQLを書いた本人がこれを説明できないなら、
そのSQLは「たまたま動いているだけ」で、
レポートとしては危うい、ということでもあります。


セキュリティ・監査の視点から見た“説明できるレポート”

「“どう計算したか説明できる数字”だけが、信頼される」

レポートは、意思決定や報告に使われます。
だからこそ、

この数字は、どういう前提で計算したのか
どのテーブルの、どのカラムを使っているのか
キャンセルや例外ケースはどう扱っているのか

を説明できることが、セキュリティ・監査の観点でも重要です。

説明できない数字は、
たとえ見た目がそれっぽくても、
「根拠のない数字」として扱われます。

Day30 でやっている「他人に説明できる状態にする」というのは、
単にプレゼンの練習ではなく、

「自分のSQLと、その結果に責任を持てる状態にする」

ということでもあります。


Day30 前半のまとめ

レポートは「ある問いに対して、前提を決めて、数字で答えるもの」であり、SQLだけでレポートを作るというのは、「対象・前提・1行の意味・出す数字」をSQLで定義する作業そのもの。
商品別売上ランキング、ユーザー別売上と購入回数、日別売上推移などのレポートは、Day29 のEC風DBを使って、JOIN+WHERE+GROUP BY+集計関数の組み合わせで素直に書ける。
SQLを書く前に「対象期間」「キャンセルの扱い」「売上の定義(単価×数量か、total_amountか)」などの前提を日本語で整理しておくと、そのまま他人への説明になるし、SQLのブレも減る。
「他人に説明できる状態」とは、SQLの文法を暗唱することではなく、「このSQLはこういう前提で、こういう単位で、こういう数字を出している」と日本語で要約できる状態のこと。
説明できるレポートだけが、監査や意思決定の場で信頼される数字になるので、「SQLを書く」と「そのSQLを言葉で説明する」をセットで練習することが、Day30 の一番大きな意味になる。

後半では、
実際に「レポート仕様」を自分で決めてSQLを書き、
それを“他人に説明するつもりで”文章化する、
というところまで一緒にやっていきます。

タイトルとURLをコピーしました