INNER JOIN・LEFT JOIN・RIGHT JOINの違いと使い分け(MySQL実例つき)

MacBook Pro with images of computer language codes SQL

SQL の結合(JOIN)は複数のテーブルを組み合わせてデータを取得する際に欠かせない機能です。INNER JOIN・LEFT JOIN・RIGHT JOIN の3種類はよく似ていますが、返す行の範囲がそれぞれ異なります。この記事では実際のテーブルとデータを使って3種類の挙動を比較し、どの場面でどれを選ぶかの判断基準を整理します。基本的な SELECT 文が書ける方を対象に、MySQL 8.0 を想定して解説します。

要点

  • INNER JOIN:両テーブルに一致する行だけを返す
  • LEFT JOIN:左テーブルの全行 + 右テーブルの一致行(なければ NULL)
  • RIGHT JOIN:右テーブルの全行 + 左テーブルの一致行(LEFT JOIN のテーブル順を入れ替えたものと同義)

このシナリオで考える

今回は「会員テーブル(members)」と「注文テーブル(orders)」の2テーブルを使います。

CREATE TABLE members (
  id   INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL
);

CREATE TABLE orders (
  id         INT PRIMARY KEY AUTO_INCREMENT,
  member_id  INT,
  amount     INT NOT NULL,
  order_date DATE NOT NULL,
  FOREIGN KEY (member_id) REFERENCES members(id)
);

INSERT INTO members VALUES (1, '田中'), (2, '鈴木'), (3, '佐藤');

INSERT INTO orders VALUES
  (1, 1, 5000, '2026-05-01'),
  (2, 1, 3000, '2026-05-10'),
  (3, 2, 8000, '2026-05-12');

会員は3人ですが、注文レコードは田中さんと鈴木さんの計3件だけです。佐藤さん(id=3)は一度も注文していない状態を前提に進めます。

INNER JOINの基本

INNER JOIN は「両テーブルに一致する行だけ」を返します。ON 句に書いた結合条件を満たさない行は結果から除外されます。

SELECT m.name, o.amount, o.order_date
FROM   members m
INNER JOIN orders o ON m.id = o.member_id;
name amount order_date
田中 5000 2026-05-01
田中 3000 2026-05-10
鈴木 8000 2026-05-12

注文のない佐藤さんは orders テーブルに行がないため、結果に現れません。INNER JOIN は「両方に存在するデータだけ見たい」場面に適しています。注文者の詳細情報を取得する、売上明細を確認するといった用途が典型例です。

JOIN とだけ書いた場合も INNER JOIN と同じ挙動になります。明示的に INNER を書くと意図が明確になり、可読性が上がります。

LEFT JOINで「片側だけ」を取る

LEFT JOIN は「左テーブル(FROM 直後)の全行」を必ず返し、右テーブルに一致する行があれば結合します。一致しない場合は右テーブルの列が NULL になります。

SELECT m.name, o.amount, o.order_date
FROM   members m
LEFT JOIN orders o ON m.id = o.member_id;
name amount order_date
田中 5000 2026-05-01
田中 3000 2026-05-10
鈴木 8000 2026-05-12
佐藤 NULL NULL

佐藤さんの行が amount=NULLorder_date=NULL で追加されました。LEFT JOIN の典型的な使いどころは「注文をしていない会員を一覧で出したい」などの「A はあるが B はない」行を抽出する場面です。

未マッチの行だけを取り出すには、WHERE 句で右テーブルの列が NULL かどうかを確認します。

-- 一度も注文していない会員を抽出
SELECT m.name
FROM   members m
LEFT JOIN orders o ON m.id = o.member_id
WHERE  o.id IS NULL;
name
佐藤

「LEFT JOIN + WHERE IS NULL」のパターンは頻出です。押さえておくと実務で役立ちます。

RIGHT JOINと代替の考え方

RIGHT JOIN は LEFT JOIN の反転で、右テーブルの全行を返します。左テーブルに一致しない場合は左側の列が NULL になります。

-- RIGHT JOIN で書く場合
SELECT m.name, o.amount
FROM   members m
RIGHT JOIN orders o ON m.id = o.member_id;

これは次の LEFT JOIN と同じ結果になります。

-- テーブル順を入れ替えて LEFT JOIN で書き直す
SELECT m.name, o.amount
FROM   orders o
LEFT JOIN members m ON o.member_id = m.id;

FROM のテーブル順を入れ替えるだけで RIGHT JOIN は LEFT JOIN に書き換えられます。JOIN の向きを統一すると読む人が混乱しにくくなるため、常に LEFT JOIN で統一しているチームも多いです。

3種類の違いを表でまとめます。

種類 返す行 典型的な用途
INNER JOIN 両テーブルに一致する行 関連データの取得
LEFT JOIN 左テーブルの全行 + 右の一致行 欠けているデータの確認・全件リスト
RIGHT JOIN 右テーブルの全行 + 左の一致行 LEFT JOIN で代替可

よくある落とし穴

WHERE 条件で LEFT JOIN が INNER JOIN になる

LEFT JOIN を使っているのに意図せず INNER JOIN と同じ結果になるケースがあります。右テーブルの列を WHERE 句で絞った場合です。

-- NG: WHERE で絞ると佐藤が除外される
SELECT m.name, o.amount
FROM   members m
LEFT JOIN orders o ON m.id = o.member_id
WHERE  o.order_date >= '2026-05-10';

佐藤さんの o.order_date は NULL のため、WHERE 条件を満たさず結果から消えます。全会員を残したまま期間を絞りたいなら、条件を ON 句へ移します。

-- OK: ON 句で絞ると佐藤(NULL 行)が残る
SELECT m.name, o.amount
FROM   members m
LEFT JOIN orders o ON m.id = o.member_id
                  AND o.order_date >= '2026-05-10';
name amount
田中 3000
鈴木 8000
佐藤 NULL

ON 句は「結合するかどうかの条件」、WHERE 句は「結合後の行を絞る条件」です。この区別を押さえるだけで LEFT JOIN 絡みのバグの大半は防げます。

NULL の比較には IS NULL を使う

NULL を比較するとき、= NULL は常に FALSE になります。NULL との比較は必ず IS NULL / IS NOT NULL を使ってください。

-- NG: NULL は = で比較できない(常に FALSE)
WHERE o.id = NULL

-- OK
WHERE o.id IS NULL

まとめ

INNER JOIN・LEFT JOIN・RIGHT JOIN の使い分けは「必要な行の範囲」で決まります。両テーブルに存在するデータだけ見たいなら INNER JOIN、片側の全行を保持したいなら LEFT JOIN を選んでください。LEFT JOIN を使う際は ON 条件と WHERE 条件の違いを意識することで、想定外の行の欠落を防げます。

参考リンク

アイキャッチ画像: Photo by Caspar Camille Rubin on Unsplash

タイトルとURLをコピーしました