はじめに
SQL を書いていると、こんな経験はありませんか?
- テーブルには確かにデータがあるのに、JOIN すると結果に出てこない
-
LEFT JOINでは出るのに、INNER JOINだと消える - 「NULL が原因」と聞いたことはあるけど、ピンとこない
本記事では
INNER JOIN と NULL(※や欠損値)の関係を
SQL 初心者向けに 具体例つきで丁寧に解説します。
この記事の対象読者
- SQL をこれからしっかり学びたい人
- JOIN の挙動の違いがまだ曖昧な人
- 「なぜ結果に行が出ないの?」を理解したい人
そもそも INNER JOIN とは?
まずは基本のイメージから。
INNER JOIN は、両方のテーブルで結合条件が一致した行だけを返す結合です。(Zenn)
つまり
- 左テーブルと右テーブルの行を使って以下のような動きをしています
-
ONで指定した条件を満たす組み合わせだけを返す - 条件に合わない行は結果に出ない
ダミーテーブルで考えてみる
注文テーブル(orders)
| order_id | customer_id | amount |
|---|---|---|
| 1 | 100 | 3000 |
| 2 | 101 | 5000 |
| 3 | 105 | 2000 |
顧客テーブル(customers)
| customer_id | customer_name |
|---|---|
| 100 | 佐藤 |
| 101 | 鈴木 |
※ 顧客テーブルには customer_id = 105 の人はいません。
INNER JOIN を実行してみる
SELECT
o.order_id,
c.customer_name,
o.amount
FROM orders o
INNER JOIN customers c
ON o.customer_id = c.customer_id;
実行結果
| order_id | customer_name | amount |
|---|---|---|
| 1 | 佐藤 | 3000 |
| 2 | 鈴木 | 5000 |
なぜ order_id = 3 の行が消えるている、、ようにみえるのか?
o.customer_id = c.customer_id
この結合条件が 一致しないから。(Zenn)
このクエリは:
-
orders.customer_id = 100→ customers に存在 → OK -
orders.customer_id = 101→ customers に存在 → OK -
orders.customer_id = 105→ customers には存在しない → ❌
一致したものだけを返すのが INNER JOIN のルール
一致しない行(105)は結果に出ない
という動きになります。
つまり INNER JOIN は結合できた行だけ返す(共通部分だけ)
→ 一致しない行は元テーブルに存在していても結果に出ないということです。(Zenn)
INNER JOIN と LEFT JOIN の違い
同じ SQL を LEFT JOIN に変えると
SELECT
o.order_id,
c.customer_name,
o.amount
FROM orders o
LEFT JOIN customers c
ON o.customer_id = c.customer_id;
LEFT JOIN の結果
| order_id | customer_name | amount |
|---|---|---|
| 1 | 佐藤 | 3000 |
| 2 | 鈴木 | 5000 |
| 3 | NULL | 2000 |
POINT:
✔ 左側(orders)の行は 全て返る
✔ 結合できなかった右側(customers)は NULL になる
これは、LEFT JOIN が
左テーブルの全行を優先して返す仕様だから。(Zenn)
勘違いしていたこと
「JOIN 結果の特定カラムが NULL になっていたら、それは JOIN のミス?」
- INNER JOIN の時 → 条件に合わない行そのものが消える
- LEFT JOIN の時 → 結合できなかった右側の値だけが NULL になる
つまり:
「カラムが NULL = その行が JOIN に失敗した」と勘違いしがちだが、
INNER JOIN ではそもそも 行そのものが出なくなる 。(Zenn)
デバッグのコツ
- INNER JOIN を ひとつずつ LEFT JOIN に変えてみる
- 結合キー側の値が 両方のテーブルに存在するかを確認する
- 「本当に INNER JOIN(共通だけ)」で良いのか再検討する
まとめ
-
INNER JOINは 両方のテーブルで一致した行だけを返す -
一致しない行は 結果に含まれない
-
LEFT JOINは 左テーブルの全行を返す- 結合できなければ右側は NULL
参考リンク(読みやすい資料)
-
Zenn:「INNER JOIN と LEFT JOIN の違いを実例で解説」 — 共通する値だけ抽出する説明あり。(Zenn)
https://zenn.dev/fd2025/articles/9bcd31a3c0188e -
Qiita:「JOIN の基本/INNER と LEFT の説明」 — 内部結合は結合できない行を返さないことの解説あり。(qiita.com)