【SQL】INNER JOINで複数テーブルを結合する

SQL

こんにちは、かつコーチです。
「注文テーブルと会員テーブルを組み合わせて、注文者の名前も一緒に表示したい」——このように、複数のテーブルにまたがるデータを1つの結果として取得したいとき、JOIN(結合)が必要になります。
今回は、もっとも基本的な結合方法であるINNER JOINを解説します。

INNER JOINとは?

複数テーブルの共通項目で行を結びつける

RDBMS(リレーショナルデータベース)では、データを1つの巨大な表に詰め込むのではなく、users(会員)テーブル、orders(注文)テーブルのように役割ごとにテーブルを分けて管理します。
INNER JOINは、この分かれたテーブル同士を、共通のカラム(多くは主キーと外部キー)を使ってつなぎ合わせる構文です。

例えば以下のようなテーブル構成を考えます。

-- users(会員)
-- id | name
--  1 | 田中
--  2 | 山田

-- orders(注文)
-- id | user_id | product_name
--  1 |       1 | ノートPC
--  2 |       1 | マウス
--  3 |       2 | キーボード

orders.user_idは、users.idと対応しています。
この対応関係を使って、注文と会員名を一緒に表示するのがJOINの役割です。

なぜテーブルを分けて結合するのか

「注文のたびに会員名も一緒に保存すればJOINは不要では?」と思うかもしれません。
しかし、会員名を注文のたびに重複して保存すると、名前変更があった際にすべての注文データを更新する必要が出てきて、データの整合性が崩れやすくなります。
テーブルを分けて必要なときにJOINする設計にすることで、データの重複と更新漏れを防げます(この考え方は正規化と呼ばれ、別記事で詳しく扱います)。

基本の書き方

INNER JOINの基本構文

INNER JOINは、ON句で結合条件を指定します。

SELECT orders.id, users.name, orders.product_name
FROM orders
INNER JOIN users ON orders.user_id = users.id;

結果は次のようになります。

id | name | product_name
 1 | 田中 | ノートPC
 2 | 田中 | マウス
 3 | 山田 | キーボード

ordersテーブルの各行に対し、user_idと一致するusers.idの行が見つかった場合にのみ、その組み合わせが結果に含まれます。

テーブルに別名(エイリアス)をつけて短く書く

テーブル名が長い場合、ASでエイリアス(別名)をつけると読みやすくなります。

SELECT o.id, u.name, o.product_name
FROM orders AS o
INNER JOIN users AS u ON o.user_id = u.id;

実務では、ASを省略してorders oのように書くこともよくあります。

INNER JOINは「一致する行だけ」を返す

ここが最も重要なポイントです。
INNER JOINは、結合条件に一致する行だけを返します。
一致しない行(例えば、まだ一度も注文していない会員)は結果から除外されます。

つまずきやすい設定・注意点

ONを書き忘れる・条件を間違えると行が爆発的に増える

INNER JOINON句を書き忘れる、または誤った結合条件を指定すると、「デカルト積」と呼ばれる、すべての組み合わせが掛け合わされた結果が返ってきます。

❌ Before(結合条件が誤っている、または欠けている)

SELECT o.id, u.name
FROM orders o
INNER JOIN users u ON 1 = 1;
-- ordersの行数 × usersの行数 の結果が返ってくる

私も新人の頃、複雑なクエリを書いていて結合条件のカラム名をタイプミスし、ON o.user_id = u.user_id(存在しないカラム名)と書いてSQLエラーになった経験があります。
さらに厄介なのは、条件自体は文法上正しいのに意味的に間違っている場合(例えば結合キーを取り違える)で、これはエラーにならずに件数が異常に増えるだけなので気づきにくいです。
JOINを書いたら、必ず結果の件数が想定と合っているか確認する癖をつけましょう。

✅ After(正しいカラムで結合し、件数も確認する)

SELECT o.id, u.name
FROM orders o
INNER JOIN users u ON o.user_id = u.id;

-- 件数チェックも忘れずに
SELECT COUNT(*) FROM orders o
INNER JOIN users u ON o.user_id = u.id;

カラム名が重複するとエラーになる

複数のテーブルに同じ名前のカラム(例えば両方にidカラムがある)がある場合、SELECT句で単にidと書くとどちらのテーブルのカラムか特定できずエラーになります。
必ずテーブル名(またはエイリアス)を付けて指定します。

-- ❌ id が曖昧でエラーになる
SELECT id, name FROM orders o INNER JOIN users u ON o.user_id = u.id;

-- ✅ テーブル名を明示する
SELECT o.id AS order_id, u.id AS user_id, u.name
FROM orders o
INNER JOIN users u ON o.user_id = u.id;

応用・一歩先の使い方

JOINは省略記法のJOINだけでも動く

MySQLでは、INNER JOINは単にJOINと書いても同じ意味になります。
ただし、「一致する行だけを取る」という意図を明示するために、私はINNER JOINと明記するスタイルを推奨しています。
これは次回解説するLEFT JOIN(一致しない行も含める結合)と対比したときに、コードを読む人が意図を誤解しにくくなるためです。

結合条件にWHEREを併用してさらに絞り込む

JOINで結合したあとに、通常のWHERE句で条件を追加すれば、結合結果からさらに絞り込みができます。

SELECT o.id, u.name, o.product_name
FROM orders o
INNER JOIN users u ON o.user_id = u.id
WHERE u.prefecture = '東京都';

東京都在住の会員の注文だけを表示する、といった使い方です。

まとめ

この記事のポイント

  • INNER JOINは、複数テーブルを共通カラムでつなぎ、一致する行だけを返す
  • ON句で結合条件を正しく指定しないと、デカルト積や誤った結果を招く
  • カラム名が重複するときは、テーブル名やエイリアスを必ず付ける
  • JOIN後もWHERE句で絞り込みを重ねられる

次に読むべき記事

  • SQL LEFT JOIN RIGHT JOIN 違い
  • SQL 複数テーブル JOIN
  • SQL 主キー・外部キーの役割と設定方法

タグ: SQL, 初心者向け, JOIN

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