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

テーブル結合の基礎(INNER JOIN/LEFT JOIN)

概要

  • 日程: Day 2 / セッション 3
  • 時間: 10:25-10:55
  • 形式: 座学
  • ゴール: INNER JOIN と LEFT JOIN の違いを「マッチしない行をどう扱うか」で説明し、適切に使い分けられる
  • 学習形式: 対話型解説

導入(5分)

これまでテーブルを1つずつ眺めてきました。employees を見れば誰が誰か分かる。departments を見れば部署名が分かる。でも、「山田太郎さんの部署名は?」と聞かれて、皆さんは答えられるでしょうか。

employees テーブルには department_id しかありません。departments テーブルには department_iddepartment_name があります。この2つをつなげて初めて「山田太郎 → 営業部」と分かるのです。

このつなぎ役が、今日の主役 JOIN(ジョイン) です。

本編(20分)

1. なぜテーブルは分かれているのか

そもそも、社員データに最初から「営業部」と書いておけばよかったのでは? という疑問が出ます。

答え:情報の重複を避けるためです。

たとえば営業部が「東京」から「横浜」に移転したとしましょう。社員テーブルに location まで持たせていたら、営業部の全員のレコードを書き換える必要があります。100人いれば100行。1人忘れたら「東京勤務になってる営業部員」が爆誕します。

部署情報は departments に1行だけ持ち、社員側は department_id参照する——これがリレーショナルデータベースの基本思想です。図書館で本ごとに著者の住所を書いておかず、「著者名簿」を別に持つようなものです。

2. INNER JOIN — 両方に存在するものだけ

コード例・実例

山田太郎さんの部署名を取り出すSQL:

SELECT 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
WHERE e.employee_id = 1;

結果:

first_name last_name department_name
太郎 山田 営業部

書き方の構造:

SELECT 列リスト
FROM 左テーブル
INNER JOIN 右テーブル
  ON 結合条件
WHERE ...;

ここがポイント

  • ON には「どの列同士で対応づけるか」を書く。多くは外部キー=主キーの組み合わせ
  • AS eエイリアス(あだ名)employees.first_namee.first_name と短く書ける
  • INNER JOIN は「両方のテーブルに該当する行だけ」を返す
flowchart LR A["employees
department_idあり"] --|INNER JOIN ON e.dept_id = d.dept_id|--> C["結合結果
両方に存在する組合せ"] B["departments
department_id"] --> C

3. INNER JOIN の落とし穴

両方に存在しないとどうなるか、考えてみましょう。

たとえば、新人さんがまだ部署未配属で department_id が NULL だとします。すると、その新人さんは INNER JOIN の結果から消えます。「該当する部署が見つからない」とみなされるためです。

これは、いわばお見合いパーティーで「両方が手を挙げた組み合わせだけ成立」ルールです。片方の手が挙がっていないと、マッチング表に名前が出てきません。

4. LEFT JOIN — 左側を全部残す

「未配属の新人さんも含めて、社員全員と所属部署を一覧したい」——そんなときが LEFT JOIN の出番です。

コード例・実例

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

FROM の側(左テーブル)の行は全部残り、右側にマッチしなかった部分は NULL になります。

first_name last_name department_name
太郎 山田 営業部
花子 鈴木 開発部
... ... ...
新人さん 未配属 NULL

ここがポイント

  • LEFT JOIN は「左側のテーブルを基準に、右側で見つかれば付ける
  • 見つからなければ右側の列は NULL
  • 「全社員を漏れなく出したい」「未紐付けも確認したい」シーンで使う
flowchart LR A["employees
全員"] --|LEFT JOIN|--> C["結合結果
社員は全員残る・
部署なしは NULL"] B["departments"] --> C

コラム — JOINで件数が増えるミステリー

JOIN初心者が必ず一度はぶつかる謎が「件数が想定より多い」現象です。たとえば顧客と注文をJOINすると、1顧客に複数注文があるとその顧客の名前が注文の数だけ現れます。「あれ、株式会社ABCが5社あるぞ……?」と慌てる前に、これは仕様です。1対多のテーブルを結合すれば「多」の側の件数になります。慣れるとむしろこれが嬉しい(明細表が作れる)ようになります。

5. RIGHT JOIN と FULL JOIN(紹介程度)

  • RIGHT JOIN:LEFT JOIN の左右が逆。右側のテーブルを基準にする
  • FULL JOIN:左右どちらに偏らず、どちらかに存在すれば全部出す(マッチしない側はNULL)

実務ではほぼ INNER と LEFT で足りるので、まずはこの2つを完璧に。RIGHT は「LEFTで書き換えれば同じ」ことから、書く人もまれです。FULL は「両側の差分を見たい」ような特殊な場面で使います。

6. 自己結合(チラ見せ)

同じテーブル同士をJOINすることもできます。たとえば「上司と部下」を1つの employees テーブルで管理しているとき、自分自身ともう一度JOINすることで「上司の名前」を出せます。これを自己結合と呼びます。詳しくは演習で必要になったら触れます。

💬 AIに聞いてみよう

  • 「INNER JOIN と WHERE で書く昔ながらの書き方(カンマ区切り)の違いは?」
  • 「LEFT JOIN と LEFT OUTER JOIN って同じ?」
  • 「JOIN を3つ以上つなげるとき、どんな順に書くのが読みやすい?」

まとめ(5分)

JOINは「複数テーブルをONで指定した条件で結びつける」操作です。違いを1行でまとめると:

  • INNER JOIN:両方に存在する組み合わせだけ
  • LEFT JOIN:左側は全部残す。右側になければ NULL

「漏らしたくない側を左に置いて LEFT JOIN」と覚えると、現場で迷いません。

次のセッションでは、employees × departmentscustomers × orders × order_items × products の2系統を実際にJOINします。INNERとLEFTで結果がどう変わるかを目で確認しましょう。

🔄 振り返りチェック

  • INNER JOIN と LEFT JOIN の違いを、ベン図のイメージで説明できますか?
  • なぜ部署情報を employees に直接持たず、別テーブルにするのでしょうか?
  • 「未配属の新人を含めた全社員一覧」を出すには、どちらのJOINを使いますか?

補足資料

  • 参考リンク: PostgreSQL公式: JOIN
  • 発展課題: 自分の身の回り(推し活、ゲーム、学校生活など)から「2つの表をJOINしたくなる例」を3つ考えてみる

学習ガイド

想定される質問と回答例

質問 ヒント
エイリアス(AS e)は必須? 必須ではないが、JOINでは事実上必須レベル。employees.first_name を毎回書くのは大変、列名が両テーブルに存在する場合は曖昧さ回避にも必要
ON と WHERE の違いは? ON は「どう結合するか」、WHERE は「結合後に絞る条件」。書き分けないと LEFT JOIN の意味が変わってしまうことがある
JOINの結果は元のテーブルより行が多くなる?少なくなる? 場合による。1対1なら同じ、1対多なら多の方に合わせて増える、INNER で片方しかなければ減る。「件数の見積もり」が大事
INNER JOIN を書かずに WHERE で同じことができる? 古い書き方では FROM employees e, departments d WHERE e.department_id = d.department_id でほぼ同じ。ただし LEFT JOIN 相当は書けない、可読性も劣る

つまずきやすいポイント

つまずきポイント ヒント
ON 条件を書き忘れ/書き間違える 全行同士の組み合わせ(直積)が出てしまう(10×5=50行など)。「想定より極端に多い」ときは ON 句を最初に疑う
INNERのつもりが LEFT、または逆 「漏らしたくない方を左に置く」と覚える。employees LEFT JOIN departments なら社員側を漏らさない
エイリアスを定義したのに元のテーブル名で書いて怒られる AS e を付けたら、以降は e.列名 で書く。employees.列名 はエラーになる
LEFT JOIN したのに右側で WHERE 条件を書いて INNER 化 LEFT JOIN の後で WHERE d.location = '東京' のように右側を絞ると、NULL の行が消えて事実上 INNER と同じになる。フィルタは ON 句に書くのが正解
読み上げを開始します...

AIに質問する