SQLのINNER JOINとLEFT JOINの違い|初心者向けに結果の差を解説

#SQL#INNER JOIN#LEFT JOIN#データベース#初心者
MAO先生と生徒うみちゃん、生徒りくちゃんが教室でSQLのINNER JOINとLEFT JOINを学ぶイラスト
MAO先生と生徒たちを紹介

この記事でわかること

  • INNER JOINLEFT JOINで結果がどう変わるか
  • 注文がない顧客も一覧へ残したいときの選び方
  • 結合条件を指定するONの役割
  • LEFT JOINの後にWHEREを使うときの注意点
  • SQLiteで試せる顧客表・注文表の完全なSQL例

結論・重要ポイント

  1. INNER JOINは、左右の表で結合条件に一致した行だけを返します。
  2. LEFT JOINは、左側の表をすべて残し、右側に一致する行がなければ右側の列をNULLにします。
  3. 注文済みの顧客だけを取得するならINNER JOIN、未注文の顧客も含めるならLEFT JOINが基本です。
  4. LEFT JOINで右表の絞り込み条件をWHEREへ書くと、未一致行が消えてINNER JOINに近い結果になることがあります。
  5. 結合前に、どちらの表を必ず残したいかを決めると選びやすくなります。

対象読者と前提知識

この記事は、SQLを学び始めて、複数の表からデータを取得したい方向けです。

SELECTで表のデータを取得できることと、顧客番号のような共通の値で表同士を関連付ける考え方が分かれば読み進められます。データベース製品ごとに細かな機能差はありますが、この記事ではSQLiteでも試せる基本的な書き方を使います。

MAO先生と学ぶINNER JOIN・LEFT JOIN

生徒うみちゃん・疑問を感じている

生徒うみちゃん

顧客表と注文表を一緒に見たいんだけど、JOINって書けば全部つながるってこと?

MAO先生・説明中

MAO先生

結合はできますが、どの行を残すかを選ぶ必要があるのです。INNER JOINなら両方の表で条件に一致した行だけ、LEFT JOINなら左側の表を基準にして未一致の行も残します。

生徒うみちゃん・興味深く聞いている

生徒うみちゃん

注文した人だけ見たいならINNER JOIN、注文していない人も見たいならLEFT JOINってこと?

MAO先生・笑顔

MAO先生

その理解で合っています。よく気づきましたね!顧客表を左側に置いてLEFT JOINすれば、注文がない顧客も一覧から消えません。

生徒りくちゃん・疑問を感じている

生徒りくちゃん

注文がない顧客では、注文番号や金額の列に何が入るのですか?空文字や0になるのでしょうか?

MAO先生・説明中

MAO先生

一致する注文がない場合、右側の表から取得する列はNULLになります。NULLは0や空文字ではなく、値が存在しない状態を表すものです。

生徒うみちゃん・自信のある表情

生徒うみちゃん

じゃあ、いつもLEFT JOINにしておけば、後から困らないじゃん!

MAO先生・注意している

MAO先生

実はINNER JOINの方がよいケースもあるのです。必要なのが注文済み顧客だけなら、未一致行を含めないINNER JOINの方が目的を明確に表せます。結果件数も意図に合わせやすくなります。

生徒りくちゃん・興味深く聞いている

生徒りくちゃん

LEFT JOINの後に、注文金額が1000円以上というWHERE条件を付けると、注文がない顧客はNULLなので消えてしまうことはないのでしょうか?

MAO先生・笑顔

MAO先生

その慎重さは大切です。右表の条件をWHEREへ置くと、未一致の行が除外されることがあります。未注文の顧客を残したまま注文側を絞りたいなら、条件をONへ含める方法を検討します。

生徒りくちゃん・自信のある表情

生徒りくちゃん

結合方法だけでなく、条件をONWHEREのどちらへ書くかも、残る行を決めるということですね!

生徒うみちゃん・喜んでいる

生徒うみちゃん

まず残したい表を左に置いて、それから未一致も必要か決めればいいんだ。名前だけ暗記するより分かりやすいじゃん!

コード・操作手順・具体例

顧客表のcustomersと注文表のordersを使います。顧客番号customer_idが2つの表を結ぶ列です。

1. サンプルデータを作る

次のSQLは、テーブル作成、データ登録、INNER JOINLEFT JOINをまとめて試せる完全な例です。

DROP TABLE IF EXISTS orders;
DROP TABLE IF EXISTS customers;

CREATE TABLE customers (
  customer_id INTEGER PRIMARY KEY,
  customer_name TEXT NOT NULL
);

CREATE TABLE orders (
  order_id INTEGER PRIMARY KEY,
  customer_id INTEGER NOT NULL,
  amount INTEGER NOT NULL
);

INSERT INTO customers (customer_id, customer_name) VALUES
  (1, '青木商店'),
  (2, '石川デザイン'),
  (3, '上田工房');

INSERT INTO orders (order_id, customer_id, amount) VALUES
  (101, 1, 1200),
  (102, 1, 800),
  (103, 2, 2500);

SELECT
  customers.customer_name,
  orders.order_id,
  orders.amount
FROM customers
INNER JOIN orders
  ON customers.customer_id = orders.customer_id
ORDER BY customers.customer_id, orders.order_id;

SELECT
  customers.customer_name,
  orders.order_id,
  orders.amount
FROM customers
LEFT JOIN orders
  ON customers.customer_id = orders.customer_id
ORDER BY customers.customer_id, orders.order_id;

顧客は3件ありますが、上田工房には注文を登録していません。この未注文の顧客が結果へ残るかどうかが、2つの結合の大きな違いです。

2. INNER JOINの結果

INNER JOINでは、顧客表と注文表の両方に一致するデータだけが返ります。

customer_nameorder_idamount
青木商店1011200
青木商店102800
石川デザイン1032500

注文がない上田工房は、注文表に一致する行がないため結果へ含まれません。

3. LEFT JOINの結果

LEFT JOINでは、左側に書いたcustomersの行がすべて残ります。

customer_nameorder_idamount
青木商店1011200
青木商店102800
石川デザイン1032500
上田工房NULLNULL

上田工房には一致する注文がないため、注文表から取得するorder_idamountNULLになります。

4. 未注文の顧客だけを探す

LEFT JOINの結果から、右側の注文番号がNULLの行を絞り込みます。

SELECT
  customers.customer_id,
  customers.customer_name
FROM customers
LEFT JOIN orders
  ON customers.customer_id = orders.customer_id
WHERE orders.order_id IS NULL
ORDER BY customers.customer_id;

この例では上田工房だけが返ります。未対応、未登録、未購入など、関連データが存在しない対象を探すときに使える形です。

5. 未注文顧客を残したまま注文金額を絞る

1000円以上の注文だけを結合しつつ、注文がない顧客も残す例です。注文側の条件をONへ含めます。

SELECT
  customers.customer_name,
  orders.order_id,
  orders.amount
FROM customers
LEFT JOIN orders
  ON customers.customer_id = orders.customer_id
  AND orders.amount >= 1000
ORDER BY customers.customer_id, orders.order_id;

青木商店の800円の注文は結合対象から外れますが、上田工房の行は残ります。

よくある誤解や失敗

LEFT JOINなら両方の表をすべて残せる

誤解です。LEFT JOINが必ず残すのは左側の表です。右側にしか存在しない行は残りません。両側の未一致行を残すFULL OUTER JOINもありますが、対応状況や書き方は利用するデータベースの公式資料で確認してください。

NULLは0や空文字と同じ

NULLは値が存在しない状態であり、数値の0や文字列の空文字とは異なります。NULLを判定するときは、等号ではなくIS NULLまたはIS NOT NULLを使います。

結合条件を書かなくても後で絞ればよい

ONUSINGを指定しない結合は、行の全組み合わせを作る結果になり、想定以上に行数が増えることがあります。どの列同士を対応させるかを明示してください。

LEFT JOINの右表条件をすべてWHEREへ書く

右表の列へWHERE条件を付けると、右表がNULLになった未一致行が除外される場合があります。左表を残す目的があるなら、条件をONへ置く場合との結果差を確認します。

一対一の結果になると思い込む

1人の顧客に複数の注文があれば、その顧客は注文数に応じて複数行になります。結合前に、関連が一対一、一対多、多対多のどれかを確認することが重要です。

Q&A

JOINだけと書いた場合はINNER JOINですか?

SQLiteやPostgreSQLでは、JOININNER JOINとして扱われます。ただし、チーム内で意図を読み取りやすくするため、この記事ではINNER JOINを明記しています。

LEFT JOINのLEFTは何を指しますか?

SQLのFROMで先に書いた表が左側、LEFT JOINの後に書いた表が右側です。左側の行をすべて残すため、どちらの表を先に置くかが重要です。

結合に使う列名は同じでないといけませんか?

同じでなくても、ON customers.customer_id = orders.customer_idのように対応関係を指定できます。USINGを使う場合は、両方の表に同じ名前の列が必要です。

LEFT JOINはINNER JOINより必ず遅いですか?

必ず遅いとは限りません。表の件数、インデックス、絞り込み条件、データベースの実行計画によって変わります。まず正しい結果になる結合を選び、性能上の問題が確認できたときに実行計画やインデックスを調べます。

要点まとめ

  • INNER JOINは両方の表で条件に一致した行だけを返す
  • LEFT JOINは左側の表をすべて残し、未一致の右表列をNULLにする
  • 未注文の顧客も残すなら、顧客表を左側にしたLEFT JOINを使う
  • LEFT JOINでは、右表の条件をONWHEREのどちらへ書くかで結果が変わる
  • 結合前に、必ず残したい表とデータ同士の関係を確認する

公式資料・参考資料

※公式情報を2026年6月23日に確認して作成しています。利用するデータベースによって対応する結合や最適化方法が異なるため、実務では対象製品の公式資料も確認してください。

データ集計や業務システムを相談できます

顧客、注文、問い合わせなどのデータは、表同士の関係を整理すると必要な情報を取り出しやすくなります。

MAO工房では、既存のExcelやCSVの整理、集計方法の見直し、小規模な業務システムの設計・開発を支援しています。お問い合わせフォームから現在の管理方法をお知らせください。

授業に登場する3人については、MAO先生のIT授業 キャラクター紹介で確認できます。

MAO工房に相談できます

データ集計や業務システムの相談ができます

Excelでは管理しにくくなった顧客・注文データの整理から、SQLを使った集計や小規模な業務システムまで、状況に合わせて支援します。

  • ✓ 既存データの整理
  • ✓ 集計方法の見直し
  • ✓ 小規模システムにも対応