JOINの種類と使い分け — テーブルを結合する
SQLのJOINで複数のテーブルを結合する方法を解説します。INNER JOINとLEFT JOINの違い、結合条件の書き方、3テーブル以上の結合まで基礎からまとめます。
リレーショナルデータベースでは、データを複数のテーブルに分けて持つのが普通です。たとえば「顧客」と「注文」は別々のテーブルにし、注文側に「どの顧客の注文か」を表す列を持たせます。こうして分かれたテーブルを、共通のキーでつなぎ合わせて1つの結果にするのが JOIN です。
なぜテーブルを分けるのか
1つの大きな表にすべてを詰め込むと、同じ情報が何度も繰り返され、更新漏れや矛盾が起きやすくなります。そこで、意味のまとまりごとにテーブルを分け、外部キーでつなぎます。
たとえば次の2つのテーブルを考えます。
customers(顧客)
| id | name | city |
|---|---|---|
| 1 | Alice | Tokyo |
| 2 | Bob | Osaka |
| 3 | Dave | Tokyo |
orders(注文)
| id | customer_id | amount |
|---|---|---|
| 1 | 1 | 500 |
| 2 | 1 | 300 |
| 3 | 2 | 800 |
orders.customer_id が customers.id を指しています。この対応関係を使って、「注文と、その注文をした顧客の名前」を一緒に取り出すのが結合です。
INNER JOIN — 両方に一致する行
もっとも基本的な結合が INNER JOIN です。両方のテーブルで結合条件を満たす行だけが結果に残ります。
SELECT orders.id, customers.name, orders.amount
FROM orders
INNER JOIN customers
ON orders.customer_id = customers.id;ON のあとに結合条件(どの列とどの列が対応するか)を書きます。この例では、注文3件それぞれに顧客名がついた結果が返ります。注文を1件も持たない顧客 Dave は、orders 側に対応行が無いため結果に現れません。
なお、INNER JOIN の INNER は省略でき、単に JOIN と書いても同じ意味になります。
LEFT JOIN — 左側は必ず残す
「注文が無い顧客も含めて、全顧客を一覧したい」場合は LEFT JOIN を使います。LEFT JOIN は、左側のテーブルの行はすべて残し、右側に対応する行が無ければ NULL で埋めます。
SELECT customers.name, orders.amount
FROM customers
LEFT JOIN orders
ON customers.id = orders.customer_id;この結果では、注文を持たない Dave も amount が NULL の行として現れます。「まだ一度も注文していない顧客」を探すといった用途で活躍します。
NULL を別の値に置き換えたいときは COALESCE が便利です。
SELECT customers.name, COALESCE(SUM(orders.amount), 0) AS total
FROM customers
LEFT JOIN orders
ON customers.id = orders.customer_id
GROUP BY customers.name;JOIN の種類まとめ
| 種類 | 残る行 |
|---|---|
INNER JOIN | 両方に一致する行だけ |
LEFT JOIN | 左テーブルは全部+右は一致分(無ければ NULL) |
RIGHT JOIN | 右テーブルは全部+左は一致分(無ければ NULL) |
FULL OUTER JOIN | どちらかにあれば残す |
実務では INNER JOIN と LEFT JOIN の2つで大半をカバーできます。RIGHT JOIN は左右を入れ替えれば LEFT JOIN で書けるため、使う場面は限られます。
3つ以上のテーブルを結合する
JOIN は続けて書くことで、3つ以上のテーブルもつなげます。たとえば「注文」「顧客」「商品」を結合する場合です。
SELECT customers.name, products.name, order_items.quantity
FROM orders
JOIN customers ON orders.customer_id = customers.id
JOIN order_items ON order_items.order_id = orders.id
JOIN products ON order_items.product_id = products.id;テーブル名が長くなってきたら、別名(エイリアス)を付けると読みやすくなります。
SELECT c.name, p.name, oi.quantity
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN order_items oi ON oi.order_id = o.id
JOIN products p ON oi.product_id = p.id;まとめ
- テーブルは意味のまとまりで分け、外部キーでつなぐ
INNER JOINは両方に一致する行だけ、LEFT JOINは左を必ず残す- 結合条件は
ONで「どの列とどの列が対応するか」を書く - 複数テーブルは
JOINを続け、別名で読みやすくする
結合は SQL の中でもつまずきやすいところですが、「どちらのテーブルを基準に、何を残したいか」を意識すると選びやすくなります。「結合(JOIN)」カテゴリの演習問題で、実際に手を動かして確認してみてください。