こんにちは、かつコーチです。
「注文テーブルと会員テーブルを組み合わせて、注文者の名前も一緒に表示したい」——このように、複数のテーブルにまたがるデータを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 JOINでON句を書き忘れる、または誤った結合条件を指定すると、「デカルト積」と呼ばれる、すべての組み合わせが掛け合わされた結果が返ってきます。
❌ 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