複数テーブルの結合
テーブルを 2 つつなぐところまでは書けても、3 つ目を足したとたんに column reference "id" is ambiguous で止まる。複数結合で最初にぶつかる壁はここです。
JOIN は下へ足していくだけ
SQL クエリ
-- レビューから本をたどり、さらに出版社までたどる
SELECT r.rating, b.title, p.name AS publisher
FROM reviews r
JOIN books b ON r.book_id = b.id
JOIN publishers p ON b.publisher_id = p.id
ORDER BY r.id;JOIN テーブル ON 条件 を縦に並べるだけで、いくつでもつなげます。読むときは上から順に、主軸からどこへ枝を伸ばしているかを追います。ここでの主軸は reviews で、books を経由して publishers までたどっています。books を飛ばして reviews から publishers へは行けません。突き合わせる列が無いからです。
どのテーブルの id なのか、データベースには分からない
SQL クエリ
-- id がどちらのものか決められずエラーになる
SELECT id, title
FROM reviews r
JOIN books b ON r.book_id = b.id;3 つのテーブルには、たいてい id という同じ名前の列があります。だから複数結合では、列に必ずテーブルの別名を付けて b.id のように書きます。
別名は 1 文字か 2 文字の小文字が定番です。reviews なら r、order_items のような複合語なら子音を拾って oi。長いテーブル名を毎回そのまま書くと 1 行が伸びて、読むのもレビューするのもつらくなります。
途中に 1 つでも内部結合が混じると、主軸が消える
SQL クエリ
-- 出版社が未設定の本も、レビューが無い本も残る
SELECT b.title, p.name AS publisher, r.rating
FROM books b
LEFT JOIN publishers p ON b.publisher_id = p.id
LEFT JOIN reviews r ON b.id = r.book_id;左を全部残したいときは、途中の結合をすべて LEFT JOIN にします。1 つでも内部結合が混じると、そこで相手のいない行が落ち、せっかく残していた主軸の行まで消えます。複数結合で件数が合わない原因は、たいていこれです。
もう一つ、行が増える方向にも気を付けてください。1 冊の本にレビューが 5 件あれば、その本は結果に 5 行並びます。そのまま SUM(b.price) のような集計をかけると、本の価格が 5 回足されて水増しされます。件数が想定と違うと感じたら、結合を 1 つずつ外して、どこで増えたのかを確かめます。
結合に使う列にインデックスが張られていないと、テーブルが大きくなった瞬間に返ってこなくなります。遅いと感じたら
EXPLAINを付けて、どの結合で全件走査になっているかを見ます。
テーブル構造
CREATE TABLE customers (
id INT PRIMARY KEY,
name VARCHAR(30)
);
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(50),
price INT
);
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT,
order_date DATE
);
CREATE TABLE order_items (
id INT PRIMARY KEY,
order_id INT,
product_id INT,
quantity INT
);
INSERT INTO customers VALUES
(1, '田中'),
(2, '鈴木'),
(3, '佐藤');
INSERT INTO products VALUES
(10, 'マウス', 2500),
(11, 'キーボード', 8000),
(12, 'モニター', 35000);
INSERT INTO orders VALUES
(1001, 1, '2026-05-01'),
(1002, 2, '2026-05-03'),
(1003, 1, '2026-05-10');
INSERT INTO order_items VALUES
(1, 1001, 10, 2),
(2, 1001, 11, 1),
(3, 1002, 12, 1),
(4, 1003, 10, 3);期待される出力
| order_id | customer_name | product_name | quantity | subtotal |
|---|---|---|---|---|
| 1001 | 田中 | キーボード | 1 | 8000 |
| 1001 | 田中 | マウス | 2 | 5000 |
| 1002 | 鈴木 | モニター | 1 | 35000 |
| 1003 | 田中 | マウス | 3 | 7500 |