SQLでよく使われるJOINは、複数テーブルを結合して、共通の情報を一つの結果にまとめるための機能です。
この節では、JOINの種類とその挙動について、基本からまとめていきます。
検証用の一時テーブルを作成する
今回の検証では、セッション内でのみ有効な TEMPORARY TABLE(一時テーブル)を使用します。これにより、環境を汚すことなくテストできます。
-- 一時テーブルがあれば削除
DROP TEMPORARY TABLE IF EXISTS orders;
DROP TEMPORARY TABLE IF EXISTS users;
-- ユーザーテーブル(TEMPORARY)作成
CREATE TEMPORARY TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50)
);
-- 注文テーブル(TEMPORARY)作成
CREATE TEMPORARY TABLE orders (
id INT PRIMARY KEY,
user_id INT,
product VARCHAR(100)
);
-- データ挿入(users)
INSERT INTO users (id, name) VALUES
(1, 'Alice'),
(2, 'Bob'),
(3, 'Carol'),
(4, 'David');
-- データ挿入(orders)
INSERT INTO orders (id, user_id, product) VALUES
(1, 1, 'Book'),
(2, 3, 'Laptop'),
(3, 1, 'Pen');

※TablePlusっていうアプリを使ってます
一時テーブルの内容を確認する
正しくデータが挿入されたか、以下のようにそれぞれのテーブルの中身を確認しておきましょう。
users テーブルの確認
SELECT * FROM users;
実行結果
+----+--------+
| id | name |
+----+--------+
| 1 | Alice |
| 2 | Bob |
| 3 | Carol |
| 4 | David |
+----+--------+
orders テーブルの確認
SELECT * FROM orders;
実行結果
+----+---------+---------+
| id | user_id | product |
+----+---------+---------+
| 1 | 1 | Book |
| 2 | 3 | Laptop |
| 3 | 1 | Pen |
+----+---------+---------+
この結果から、Alice(ID 1)は2件、Carol(ID 3)は1件の注文を持ち、Bob(ID 2)とDavid(ID 4)は注文がないことが分かります。
JOINの種類
INNER JOIN
- 両方のテーブルに対応する行がある場合のみを結合
- 最も基本的なJOIN
- JOINと書いても使える(業務的にはINNER JOINに統一した方が使いやすいよ…)
- ユースケース:顧客と注文の対応表
SELECT *
FROM users u
INNER JOIN orders o ON u.id = o.user_id;
実行結果
+----+--------+----+---------+-----------+
| id | name | id | user_id | product |
+----+--------+----+---------+-----------+
| 1 | Alice | 1 | 1 | Book |
| 1 | Alice | 3 | 1 | Pen |
| 3 | Carol | 2 | 3 | Laptop |
+----+--------+----+---------+-----------+
LEFT JOIN (LEFT OUTER JOIN)
- 左側のテーブルはすべて結果に含める
- 対応する行がなければNULLが入る
- ユースケース:顧客の注文履歴
SELECT *
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
実行結果
+----+--------+------+---------+-----------+
| id | name | id | user_id | product |
+----+--------+------+---------+-----------+
| 1 | Alice | 1 | 1 | Book |
| 1 | Alice | 3 | 1 | Pen |
| 2 | Bob | NULL | NULL | NULL |
| 3 | Carol | 2 | 3 | Laptop |
| 4 | David | NULL | NULL | NULL |
+----+--------+------+---------+-----------+
RIGHT JOIN (RIGHT OUTER JOIN)
- LEFT JOINの逆で、右側のテーブルを保証
- ユースケース:注文履歴と注文した顧客
- (ぶっちゃけ可読性が悪くなるのでLEFT JOINだけ使って欲しい)
SELECT *
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;
実行結果
+----+--------+----+---------+-----------+
| id | name | id | user_id | product |
+----+--------+----+---------+-----------+
| 1 | Alice | 1 | 1 | Book |
| 3 | Carol | 2 | 3 | Laptop |
| 1 | Alice | 3 | 1 | Pen |
+----+--------+----+---------+-----------+
FULL OUTER JOIN
- 両方のテーブルのすべての行を結果に含める
- MySQLは本来サポートしていないため、UNIONなどで表現する必要あり
- ユースケース:マスターとサブを比較して欠損データがないか確認する
SELECT *
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
UNION
SELECT *
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;
本記事ではJOINの種類と基本動作を確認しました。実行例はぜひ手元で試してみてください。
次回の記事では、LEFT JOINとINNER JOINを使った場合の実行計画(EXPLAIN)の違いと、それがパフォーマンスに与える影響を具体的に検証していきます。
更新情報はX(旧Twitter)で配信中。気になる方はフォローをお願いします!
