SQL INNER JOIN: 2 テーブルの一致行を結合
SQL の INNER JOIN では、結合条件が両テーブルで一致する行だけを返します。レコードと参照値を紐付けるような関連データの結合に使い、一致しない行を結果から除外したいときに適しています。結合述語を両側が満たす必要があるため、結合キーが NULL の行や対応行がない行は自動的に除外されます。
関連テーブルを結合する SQL INNER JOIN の例
出力:
ここに出力が表示されます...
出力:
+----------+------------+
| employee | department |
+----------+------------+
| Alma | 開発 |
| Ben | 開発 |
| Cara | 営業 |
+----------+------------+
3 row(s)
この例の仕組み
departmentsには 3 つの部署、employeesには 4 人の従業員を入れ、各行が外部キーdept_idを持ちます。Dan のdept_idは NULL です。INNER JOIN departments d ON d.id = e.dept_idは、従業員のdept_idと部署のidが一致する行同士を組み合わせます。両側が一致した組だけが残ります。- Dan は
dept_id = NULLです。=演算子はどちらかのオペランドが NULL のとき unknown になるため、Dan はどの部署とも一致せず除外されます。 - 人事部(id 3)を参照する従業員はいないため、この部署も結果に現れません。INNER JOIN は両側の不一致行を落とします。
SQL INNER JOIN とは?
INNER JOIN は、結合述語に基づく 2 テーブルの共通部分を返します。論理的には ON 条件が true になる行ペアだけを保持します。物理実行はエンジンやデータ形状により変わります(nested loops、hash join、merge join)が、結果集合に含まれるのは常に一致行だけです。
INNER JOIN と LEFT JOIN の違い
| INNER JOIN | LEFT JOIN |
|---|---|
| 両テーブルで一致した行だけを返す | 左テーブルの全行を返し、一致がなければ右側列は NULL になる |
| 不一致行は暗黙的に除外される | 左側の不一致行は保持され、右側の列が NULL で埋まる |
| 一致しないことが不正データを意味する場合に使う | 一致の有無にかかわらず左側の全レコードを見たい場合に使う |
原則: すべての結果行で両テーブルの有効なデータが必要なら INNER JOIN を選びます。右側に一致がなくても行を残したいなら LEFT JOIN に切り替えます。
SQL INNER JOIN でよくある間違い
結合条件の欠落、または常に真の条件
ON 句を省略したり、常に真になる条件を使ったりすると、直積になります。つまり、すべての従業員行がすべての部署行と組み合わされます。
-- 誤り: 直積(4 × 3 で 12 行)
SELECT * FROM employees, departments;
-- 正解: 結合条件を明示する
SELECT * FROM employees e
INNER JOIN departments d ON d.id = e.dept_id;
一意でない結合キーによる行の増殖
INNER JOIN は一致した行ペアごとに 1 行を返します。一意でないキーを持つテーブルに結合すると、左側 1 行が右側の複数行に一致し、結果が意図せず増えることがあります。
INNER JOIN と EXISTS の使い分け
出力に両テーブルの列が必要なら INNER JOIN を使います。関連行が存在するかどうかで絞り込むだけなら EXISTS を使います。サブクエリが複数行に一致する場合、EXISTS は行の増殖を避けられ、クエリプランナは最初の一致で探索を打ち切れることが多いです。
-- EXISTS: 一致する部署がある従業員を 1 行ずつ返す
SELECT e.name FROM employees e
WHERE EXISTS (SELECT 1 FROM departments d WHERE d.id = e.dept_id);
パフォーマンスの注意点
結合述語で使う列(この例では dept_id と departments.id)にインデックスを作成します。インデックスがないと、エンジンは内側テーブルを何度も走査する可能性があります。大きなテーブルでは EXPLAIN QUERY PLAN で実行計画を確認し、SCAN ではなく USING INDEX や SEARCH が出ているかを確認してください。