Webアプリのデータは、1つのテーブルだけで完結しないことが多いです。ユーザー、注文、商品、コメントなどを分けて保存し、必要なときにJOINでつなぎます。
一言でいうと
JOINは、別々のテーブルに分かれたデータを、共通するキーを使って1つの結果として読むための仕組みです。
例にするテーブル
users と orders を考えます。
| users.id | users.name |
|---|---|
| 1 | Sato |
| 2 | Suzuki |
| 3 | Tanaka |
| orders.id | orders.user_id | orders.total |
|---|---|---|
| 101 | 1 | 3000 |
| 102 | 1 | 1500 |
| 103 | 2 | 5000 |
orders.user_id が users.id を参照しています。
INNER JOIN
INNER JOIN は、両方のテーブルで対応する行がある場合だけ結果に残します。
SELECT users.name, orders.total
FROM users
INNER JOIN orders ON users.id = orders.user_id;
この結果には、注文があるユーザーだけが出ます。注文がない Tanaka は出ません。
| name | total |
|---|---|
| Sato | 3000 |
| Sato | 1500 |
| Suzuki | 5000 |
INNER JOINは「両方に存在するデータだけ」を見たいときに使います。
LEFT JOIN
LEFT JOIN は、左側のテーブルの行を必ず残します。右側に対応する行がない場合、右側の列は NULL になります。
SELECT users.name, orders.total
FROM users
LEFT JOIN orders ON users.id = orders.user_id;
この結果には、注文がないユーザーも出ます。
| name | total |
|---|---|
| Sato | 3000 |
| Sato | 1500 |
| Suzuki | 5000 |
| Tanaka | NULL |
LEFT JOINは「右側にデータがなくても、左側の一覧を残したい」ときに使います。
ON条件の役割
ON は、どの列同士を対応させるかを指定します。
ON users.id = orders.user_id
これは、「ユーザーの id と注文の user_id が一致する行をつなぐ」という意味です。
JOINで結果がおかしいときは、まず ON 条件を確認します。
WHEREとの違い
JOINの ON と WHERE は役割が違います。
| 句 | 役割 |
|---|---|
ON | テーブル同士のつなぎ方を決める |
WHERE | JOIN後の結果を絞り込む |
特に LEFT JOIN では、右側テーブルの条件を WHERE に書くと、意図せず INNER JOIN のような結果になることがあります。
どちらを使うか
| やりたいこと | 使うJOIN |
|---|---|
| 注文があるユーザーだけ見たい | INNER JOIN |
| 注文がないユーザーも含めたい | LEFT JOIN |
| 親データ一覧を全部出したい | LEFT JOIN |
| 関連データが存在するものだけ出したい | INNER JOIN |
よくある誤解
| 誤解 | 実際 |
|---|---|
| JOINはテーブルを物理的に合体する | 結果として一時的につないで表示します |
| LEFT JOINは常に安全 | WHERE条件次第で意図しない結果になります |
| ON条件は何でもよい | 間違えると件数が増えたり減ったりします |
| JOINは必ず重い | 適切なキーとインデックスがあれば一般的に使われます |
まとめ
INNER JOIN は両方に対応する行があるものだけを返し、LEFT JOIN は左側の行を残したまま右側の情報をつなぎます。JOINを読むときは、まず対象テーブル、次に ON 条件、最後に WHERE 条件を確認します。