📖 テーマ設定
🔊 音声設定
1.2
1.0
1.0
▶️ 再生コントロール
🎵 BGM設定
0.3
🔔 効果音設定
0.3

JOIN演習(顧客と注文をつなぐ)

概要

  • 日程: Day 2 / セッション 4
  • 時間: 10:55-11:40
  • 形式: 実習
  • ゴール: employees×departments、customers×orders×order_items×products を結合する SQL を 3 本書け、INNER と LEFT の結果差を説明できる
  • 学習形式: ハンズオン実習(AIペアプログラミング)

導入(5分)

前のセッションで「テーブルをつなぐとはどういうことか」を頭で理解しました。今度は、自分の手で実際にJOINを書いて、画面に出てくる結果を見て、「あ、本当に名前と部署名が一緒に出てきた!」という感動を味わってもらいます。

特に今日のハイライトは、customers → orders → order_items → products という4テーブルJOIN。これができると、「3月に株式会社ABCが何をいくつ買ったか」みたいな業務でよくある問いに、SQL一発で答えられるようになります。

本編(10分)

1. JOINで使うエイリアスの設計

複数テーブルをJOINするときは、最初に短いエイリアスを決めると書きやすくなります。

テーブル名 エイリアス例
employees e
departments d
customers c
orders o
order_items oi
products p
categories cat

エイリアスを付けたら、以降の列指定は e.first_name のように書きます。これで「どのテーブルの first_name か」が一目瞭然です。

2. 4テーブルJOINの考え方

「customers が何をいくつ買ったか」を出すには、4つのテーブルを下図のようにつなぎます。

flowchart LR C["customers
c"] --|c.customer_id = o.customer_id|--> O["orders
o"] O --|o.order_id = oi.order_id|--> OI["order_items
oi"] OI --|oi.product_id = p.product_id|--> P["products
p"]

書く順番は「左から右に流れる」ようにすると読みやすい。JOIN は何個でもつなげられますが、ON句を間違えると結果が爆発するので、一つずつ追加して確認するのがコツです。

💬 AIに聞いてみよう

  • 「3テーブル以上のJOINで、ON句の書き方のコツは?」
  • 「JOINした結果の件数が想定と違うとき、どう調査すればいい?」
  • SELECT * で全列出すと、JOIN後はどう表示される?」

実習・演習(30分)

課題

課題1: employees × departments で「誰がどこの部署か」一覧

すべての社員と所属部署名を、社員ID順に表示してください。

期待する列:employee_id, first_name, last_name, department_name

-- ヒント: INNER JOIN
SELECT e.employee_id, e.first_name, e.last_name, d.department_name
FROM employees AS e
INNER JOIN departments AS d
  ON e.department_id = d.department_id
ORDER BY e.employee_id;

実行したら、件数を確認してください(10件のはず)。

課題2: INNER と LEFT の結果差を体感する

次のSQLをそれぞれ実行し、件数を比較してください。

-- INNER JOIN
SELECT d.department_name, e.first_name
FROM departments AS d
INNER JOIN employees AS e
  ON d.department_id = e.department_id;

-- LEFT JOIN(departments側を基準に)
SELECT d.department_name, e.first_name
FROM departments AS d
LEFT JOIN employees AS e
  ON d.department_id = e.department_id;

差を観察するために、次のSQLでテストデータを足してから再実行してみてください(BEGIN/ROLLBACK で囲んで安全に):

BEGIN;
INSERT INTO departments (department_name, location) VALUES ('総務部', '東京');
-- INNERとLEFTを再実行
-- ...
ROLLBACK;

期待する観察:

  • INNER:「総務部」が出てこない(社員0人なので消える)
  • LEFT:「総務部」が出る、ただし first_name は NULL

課題3: customers × orders で「誰がいつ、いくら注文したか」

注文日順に、顧客名・注文日・合計金額を表示してください。

SELECT c.customer_name, o.order_date, o.total_amount
FROM customers AS c
INNER JOIN orders AS o
  ON c.customer_id = o.customer_id
ORDER BY o.order_date;

実行後、「8人の顧客に対して10件の注文がある」「同じ顧客が複数回出てくる」ことを確認してください。

課題4: 4テーブルJOIN — 「誰が何をいくつ買ったか」

customers × orders × order_items × products を結合し、注文ごとの明細を表示してください。

期待する列:customer_name, order_date, product_name, quantity, unit_price

SELECT c.customer_name,
       o.order_date,
       p.product_name,
       oi.quantity,
       oi.unit_price
FROM customers AS c
INNER JOIN orders AS o      ON c.customer_id = o.customer_id
INNER JOIN order_items AS oi ON o.order_id = oi.order_id
INNER JOIN products AS p     ON oi.product_id = p.product_id
ORDER BY o.order_date, c.customer_name;

課題5(チャレンジ): 集計と組み合わせる

課題4を発展させ、顧客ごとの購入金額合計を出してください。

  • 列:customer_name, 合計金額
  • 合計金額は SUM(oi.quantity * oi.unit_price) で計算
  • GROUP BY c.customer_nameORDER BY 合計金額 DESC で並べる

成果物

以下を1ファイルにまとめてください。

  • 課題1〜4の実行SQLと結果(先頭の5行程度でOK)
  • 課題2でINNERとLEFTの件数差が何件だったか、その理由
  • 課題5の結果と、トップ3顧客の名前

ヒント

  • JOINが多くなったら、まず2テーブルだけで成立させて、1つずつ足していく
  • 結果の件数が想定より多い/少ないときは、まずJOINを1段階ずつ外して確認
  • AIに「このSQLが何をしているか日本語で説明して」と頼むと、自分の理解確認に使える

まとめ(5分)

JOINで世界が広がったはずです。1つのテーブルでは答えられなかった「誰が、何を、いつ、いくつ買ったか」がワンクエリで取れる——これは現場で本当によく使うパターンです。

特に大事なポイント:

  • エイリアスを使う(短く、テーブル頭文字が定番)
  • 1つずつJOINを追加して件数を確認する
  • INNERとLEFTの違いはマッチしない行の扱い

次のセッションでは、JOINの結果に必ず登場する「NULL」と、条件分岐の CASE 式を学びます。たとえばLEFT JOINで出てきた NULL を「未配属」と表示するなど、結果を見やすく整える技です。

🔄 振り返りチェック

  • 4テーブルJOINを、何も見ずに ON句までスラスラ書けますか?
  • INNER と LEFT で件数差が出る場面の具体例を1つ言えますか?
  • JOIN後の件数が「想定より多い」とき、原因をどう調べますか?

補足資料

  • 発展課題: 「3月の注文だけを対象に、商品カテゴリ別の売上ランキング」を出すSQLを書いてみる(categoriesテーブルも加えた5テーブルJOIN)

学習ガイド

想定される質問と回答例

質問 ヒント
同じ顧客名が複数行に出るのはなぜ? 1顧客×複数注文だから。明細表としては正常。集計したいなら GROUP BY を使う
エイリアスは何文字でもいい? 何文字でもOKだが、慣習的には1〜3文字。テーブル頭文字(e, d, c, o)がよく使われる
JOINの順番を変えても結果は同じ? INNER JOINだけなら結果は同じ(順番は実行計画の話)。LEFT JOIN を混ぜると順番で意味が変わる
SELECT * でJOINすると同じ名前の列はどうなる? 両方とも出力される。表示上は同じ列名で並ぶが、内部的には別物。明示的に列を選ぶのが安全

つまずきやすいポイント

つまずきポイント ヒント
ON 句で = の片側にエイリアスを書き忘れる ON department_id = department_id だとどちらの department_id か曖昧でエラー。ON e.department_id = d.department_id と必ず両側に
件数が想定より多い(行が増える) 1対多のJOINでは「多」の数だけ増える。集計したいときは GROUP BY、明細を出したいなら受け入れる
LEFT JOIN したのに NULL の行が消える 右側テーブルの列を WHERE で絞ると、その NULL が落ちる。フィルタは ON句に入れる
エイリアスを使い始めた途端、列が見つからないエラー エイリアスを定義した後は、元のテーブル名は使えない。employees.列名e.列名 に統一
読み上げを開始します...

AIに質問する