結合の実践演習
結合の実践演習 とは
複数のテーブルを結合する実践的な演習です。JOIN句を使いこなしましょう。本レッスンでは、結合の実践演習 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
なぜ重要か
ここまで学んだ INNER JOIN / OUTER JOIN / SELF JOIN / 集合演算を組み合わせ、実務でよくある「売上分析レポート」を作る練習をします。1 つのクエリで複数の結合・集計・並び替えをこなすパターンは、現場のレビューでよく出題されるシナリオです。型に慣れておくと、どんなデータベースを触っても応用が効きます。実際のレポート業務では「結合 + 集計 + 並び替え + ゼロ表示」がワンセットで求められることがほとんどで、このレッスンの 1 本を書き切れるかが SQL の中級ラインの目安と言えます。
実践シナリオ — 商品ごとの売上集計
3 テーブルが用意されています。products (商品マスタ)、orders (注文ヘッダ)、order_items (注文明細) です。これを使って商品ごとに次の情報を出すレポートを作ります。
- 商品名
- 注文された個数の合計
- 売上 (price × quantity の合計)
- 注文が 1 件もない商品も「0 個・0 円」で残す
設計のステップ
左に products を置き、order_items を LEFT JOIN するのがポイントです。INNER JOIN にすると未販売商品が消えてしまいます。「主軸を左に、関連を右に」がレポート系 SQL の基本姿勢です。
ステップ 1 — 結合だけ書いてみる
SQL クエリ
SELECT p.id, p.name, oi.quantity, p.price
FROM products p
LEFT JOIN order_items oi ON p.id = oi.product_id;まずは結合だけを書いて、未販売商品が NULL で残ることを確認します。期待通り NULL が混じったら、次は集計を足していきます。
ステップ 2 — 集計をかける
SQL クエリ
SELECT p.id, p.name,
COALESCE(SUM(oi.quantity), 0) AS qty,
COALESCE(SUM(oi.quantity * p.price), 0) AS revenue
FROM products p
LEFT JOIN order_items oi ON p.id = oi.product_id
GROUP BY p.id, p.name
ORDER BY revenue DESC, p.id;GROUP BY と SUM を加えれば商品ごとの集計レポートが完成します。COALESCE(SUM, 0) で未販売商品は 0 に丸めます。
落とし穴
LEFT JOIN + GROUP BY で集計するときは、SUM の結果が NULL になり得ることを忘れがちです。
COALESCE(SUM(...), 0)で 0 に変換すれば、レポート上で「未販売 = 空白」ではなく「未販売 = 0」と明示できます。経営層に出すレポートでは「空白」より「0」のほうが意図が伝わりやすいので、この一手を入れる癖をつけておきましょう。
GROUP BY に書く列は SELECT 句の非集計列とすべて一致させてください。Postgres / 標準 SQL では
p.id, p.nameの両方を GROUP BY に書く必要があります。MySQL の緩いモード (ONLY_FULL_GROUP_BY 無効) に慣れていると忘れがちなので注意。本番環境でモードが変わったときに動かなくなるパターンの典型です。
演習で扱う 3 テーブル
SQL クエリ
products (id, name, price)
orders (id, order_date)
order_items (id, order_id, product_id, quantity)商品マスタは 5 件、注文は 3 件、明細は 4 件用意してあります。商品の中には注文 0 件のものも含まれているので、LEFT JOIN を忘れないようにしてください。
発展課題のヒント
もし余裕があれば、orders.order_date を JOIN に追加して「今月だけの売上」を出してみると、さらに実務に近い練習になります。o.order_date >= '2026-05-01' のような条件を ON 句または WHERE 句のどちらに書くかで結果が変わるので、両方試してみると LEFT JOIN の挙動への理解が深まります。
チェックリスト
この演習を完成させる前に、次のチェックリストを確認してみてください。
- 出力列名が
product_id,product_name,total_quantity,total_revenueになっているか - 未販売商品 (ヘッドセット、ウェブカメラ) が結果に残っているか
total_revenueが降順、同点ならproduct_id昇順で並んでいるか- COALESCE で NULL を 0 に変換しているか
- GROUP BY に
p.idとp.nameの両方が含まれているか
この 5 つを満たせば合格です。実務でこの形を書けることは、SQL 中級の重要な指標になります。
まとめ
- 主軸テーブルを左に置き、LEFT JOIN で広げる
- 未集計の
NULLはCOALESCEで 0 に丸める - GROUP BY は SELECT 句の非集計列をすべて含める
- 並び順は ORDER BY revenue DESC, id ASC のように複数指定が可能
- 条件を
ONとWHEREのどちらに書くかでOUTER JOINの効果が変わる - チェックリストで自分のクエリを最終確認する習慣を付ける
次のレッスン
次は テーブル結合クイズ です。テーブル結合の理解度をクイズで確認!複数のテーブルからデータを抽出する力を試しましょう。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- 結合 実践 の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. 結合 実践 とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
テーブル構造
schema.sql
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(50),
price INT
);
CREATE TABLE orders (
id INT PRIMARY KEY,
order_date DATE
);
CREATE TABLE order_items (
id INT PRIMARY KEY,
order_id INT,
product_id INT,
quantity INT
);
INSERT INTO products VALUES
(1, 'マウス', 2500),
(2, 'キーボード', 8000),
(3, 'モニター', 35000),
(4, 'ヘッドセット', 6000),
(5, 'ウェブカメラ', 4500);
INSERT INTO orders VALUES
(1001, '2026-05-01'),
(1002, '2026-05-03'),
(1003, '2026-05-10');
INSERT INTO order_items VALUES
(1, 1001, 1, 3),
(2, 1001, 2, 1),
(3, 1002, 3, 1),
(4, 1003, 1, 2);期待される出力
| product_id | product_name | total_quantity | total_revenue |
|---|---|---|---|
| 3 | モニター | 1 | 35000 |
| 1 | マウス | 5 | 12500 |
| 2 | キーボード | 1 | 8000 |
| 4 | ヘッドセット | 0 | 0 |
| 5 | ウェブカメラ | 0 | 0 |