INNER JOINの基本
このレッスンで分かること
INNER JOINは両側に一致行があるレコードだけ返す結合 (内部結合)- 結合条件は
ON、絞り込みはWHEREに書き分けるのが習慣NULL = NULLは真でないので、結合キーが NULL の行は消える
INNER JOINの基本 とは
複数のテーブルを組み合わせてデータを取得するINNER JOINを学びます。本レッスンでは、INNER JOINの基本 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
なぜ重要か
業務でもっとも頻繁に使う結合が INNER JOIN (内部結合) です。注文があった顧客だけを抽出したいとき、購入実績がある商品だけを集計したいとき、両側のテーブルに「ちゃんと一致するレコードがある」ものだけを取り出すのが INNER JOIN です。結合の基本中の基本であり、ここを理解せずに OUTER JOIN や複数結合に進むと混乱するので、まずはこの 1 つを完全に押さえます。実務の SQL の体感 7 〜 8 割は INNER JOIN ベースで、まずこの 1 種類を完全マスターすれば SELECT の表現力が大きく広がります。
構文
INNER JOIN の基本構文は次のとおりです。INNER は省略でき、JOIN と書いただけでも内部結合として扱われます。
SQL クエリ
SELECT 列
FROM 左テーブル AS L
INNER JOIN 右テーブル AS R
ON L.キー = R.キー;結合条件は ON 句で指定し、WHERE 句とは役割が違います。ON は「結合の条件」、WHERE は「結合後の絞り込み」です。INNER JOIN の場合はどちらに書いても結果は同じになることが多いですが、SQL の意図を読みやすくするために役割で分けて書く習慣を付けましょう。
ステップごとの動作
INNER JOIN は「両方のテーブルに一致行があるレコードだけを取り出す」操作です。下図は社員 (employees) と部署 (departments) を department_id で結合する例です。
INNER JOIN の挙動を表で整理すると、次のとおりです。
| 状況 | INNER JOIN の結果 |
|---|---|
| 両側に一致 | 両方の列が結合された行が出る |
| 片側だけ | その行は結果に出ない |
| 結合キーが NULL | NULL は等しくないので消える |
| 重複あり | デカルト積的に行数が増える |
たとえば社員に「未割当 (department_id が NULL)」がいたり、部署に「社員ゼロの部署」があったりすると、INNER JOIN の結果からは消えます。これが INNER JOIN の「内側だけ残す」という意味です。
代表例 1 — 注文と顧客
SQL クエリ
SELECT o.id, c.name, o.amount
FROM orders o
INNER JOIN customers c
ON o.customer_id = c.id;注文と顧客を結合し、注文ごとに顧客名を取得します。customers 側に対応する行がない注文 (たとえば退会済み顧客の注文) は結果から除外されます。データの整合性を確認しながらレポートを作るときに役立つパターンです。
代表例 2 — 商品と在庫
SQL クエリ
SELECT p.name, s.quantity
FROM products p
JOIN stocks s ON p.id = s.product_id
WHERE s.quantity > 0;在庫が登録されている商品だけが結果に出ます。在庫レコードがない商品 (廃番予定など) は INNER JOIN の段階で除外され、さらに WHERE で quantity > 0 を満たすものに絞られます。
ON と WHERE の違い
初心者が混乱しやすいのが ON と WHERE の使い分けです。
ON は「結合の条件」、WHERE は「結合した結果に対する絞り込み」。INNER JOIN では実質どちらに書いても同じ結果になりますが、可読性のために結合キーは ON、フィルタは WHERE と分けるのが慣習です。OUTER JOIN だと挙動が変わるので、習慣として身につけておくと混乱しません。
落とし穴 — NULL は結合に使えない
NULL = NULLは SQL では「真」になりません。結合キーに NULL がある行は INNER JOIN の結果に出ません。たとえば社員のdepartment_idが NULL だと、その社員は部署と結合できず消えます。これを救うには OUTER JOIN や、COALESCEを ON 句で使って NULL を別の値に置き換えるテクニックが必要です。
ベストプラクティス
- テーブルには必ず短い別名 (1-2 文字) をつける
- ON 句にはキー結合だけ、WHERE 句にはフィルタを書く
- SELECT 句では
テーブル別名.列名で曖昧さを排除 - 複数 INNER JOIN を縦に並べるときも、上から順に「主軸 → 関連」と読み下せる順序にする
実例 — 売上のあった商品だけを抽出
SQL クエリ
SELECT p.id, p.name, SUM(oi.quantity) AS sold
FROM products p
JOIN order_items oi ON p.id = oi.product_id
GROUP BY p.id, p.name
ORDER BY sold DESC;INNER JOIN を使うことで「1 個も売れていない商品」が結果から除外されます。「売上ランキング」を出すときは、未販売商品を結果に含めないこの形が便利です。逆に「未販売商品を含む全商品リスト」が欲しいなら LEFT JOIN に切り替えます。
ここまでの要点
INNER JOIN は両側一致だけ残す。ON は結合条件、WHERE はフィルタと役割を分ける。結合キーの NULL は消える、OUTER JOIN への切り替えで救う。
まとめ
- INNER JOIN は両側に一致行があるレコードだけを返す
- 結合条件は
ON句、絞り込みはWHERE句に書く NULLは結合キーとして使えないのでOUTER JOINを検討する- 別名 (AS) をつけると複数テーブル参照が読みやすくなる
- 「ランキング」「実績集計」など、データのある側だけ残す用途に最適
次のレッスン
次は LEFT/RIGHT OUTER JOIN です。LEFT/RIGHT OUTER JOINを使い、テーブル間の連携を深めましょう。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- INNER JOIN の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. INNER JOIN とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
テーブル構造
schema.sql
CREATE TABLE departments (
id INT PRIMARY KEY,
name VARCHAR(30)
);
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(30),
department_id INT,
salary INT
);
INSERT INTO departments VALUES
(1, '営業'),
(2, '開発'),
(3, '人事'),
(4, '総務');
INSERT INTO employees VALUES
(101, '田中', 1, 350000),
(102, '鈴木', 2, 420000),
(103, '佐藤', 2, 380000),
(104, '高橋', 3, 320000),
(105, '山田', NULL, 300000);期待される出力
| employee_id | employee_name | department_name | salary |
|---|---|---|---|
| 101 | 田中 | 営業 | 350000 |
| 102 | 鈴木 | 開発 | 420000 |
| 103 | 佐藤 | 開発 | 380000 |
| 104 | 高橋 | 人事 | 320000 |