複数テーブルの結合

複数テーブルの結合 とは

複数のテーブルを結合し、関連するデータを効率的に取得します。本レッスンでは、複数テーブルの結合 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

なぜ重要か

実務で書く SQL は、2 テーブルではなく 3 〜 5 テーブルを結合することが普通です。たとえば「どの顧客が、いつ、どの商品を、いくらで買ったか」を 1 行にまとめるには、customersordersorder_itemsproducts の 4 テーブルを結合する必要があります。1 つの JOIN を覚えるだけでは足りず、複数の JOIN を連結する書き方と「読みやすさ」のコツを身につけることが、SQL レビューでも実務でも差になります。EC、業務システム、ダッシュボード — どんなプロダクトでも 3 〜 4 テーブル結合は基本動作になります。

構文 — JOIN を連結する

複数結合は JOIN を縦に並べていくだけです。それぞれに ON 句で結合条件をつけます。

SQL クエリ

SELECTFROM A JOIN B ON A.x = B.x JOIN C ON B.y = C.y JOIN D ON C.z = D.z;

結合の順序は、書いた順に左から処理されるイメージで読みます (オプティマイザは実行時に並び替えますが、論理モデルとしては左から)。SQL を読むときは「主軸テーブルからどう枝葉を広げているか」を 1 行ずつ追いかけると、設計者の意図が見えてきます。

ステップごとの動作

下の図は注文情報を 4 テーブルから組み立てる流れです。

diagram (will load when visible)

代表例 1 — 注文ヘッダと顧客と商品を結ぶ

SQL クエリ

SELECT o.id AS order_id, c.name AS customer, p.name AS product, oi.quantity, p.price 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 ORDER BY o.id;

注文 → 顧客 → 注文明細 → 商品の順に結合し、注文 1 件ごとに購入商品の行が並ぶレポートが作れます。注文明細が複数あれば、同じ注文 ID が複数行に並びます。

代表例 2 — INNER と LEFT を混ぜる

SQL クエリ

SELECT c.name, COUNT(o.id) AS order_count, COALESCE(SUM(p.price * oi.quantity), 0) AS total FROM customers c LEFT JOIN orders o ON c.id = o.customer_id LEFT JOIN order_items oi ON oi.order_id = o.id LEFT JOIN products p ON oi.product_id = p.id GROUP BY c.id, c.name;

顧客側は LEFT JOIN で全件残し、注文がない顧客でも行が消えないようにします。途中で 1 つでも INNER JOIN が混じると未購入顧客が消えるので注意です。LEFT JOIN を縦に並べた場合、上から見て「左側を全件残したい主軸」を見失わないことがポイントです。

別名 (エイリアス) の付け方

複数テーブルを使うとき、別名を短くつけると一気に読みやすくなります。

別名は 1-2 文字の小文字 (c, o, oi, p) が定番。長い名前のテーブルを毎回フルで書くと SQL がすぐ 100 文字超えになり、レビューしづらくなります。複合語の場合 (order_items) は子音だけ取って oi のように略すと読みやすくなります。

落とし穴 — 結合キーが部分一致しか保証されないとき

複数結合で気をつけるのは「結合キーが NULL を含むケース」と「同名カラムの曖昧参照」です。同じ id 列が複数テーブルにあるので、SELECT 句や ORDER BY で必ずテーブル別名を付けて参照します。SELECT id だけ書くと "column reference is ambiguous" エラーになります。チームのレビューでも最頻出の指摘ポイントです。

パフォーマンスの観点

複数結合は実行計画 (EXPLAIN) を必ず見ながら作ります。結合キーにインデックスが張られていれば数百万行でも数百ミリ秒で返りますが、結合キーが文字列で型ミスマッチがあるとフルスキャンになります。実務では「インデックスがあるか」「結合する順番が効率的か」を意識すると、急に遅くなったクエリの原因が見えるようになります。

書き方のスタイル

複数結合では、ON 句を JOIN 行と同じ行に書くか、別行にインデントするかで読みやすさが変わります。チームによってスタイルが違うので、参画したプロジェクトの既存 SQL に合わせるのが無難です。個人で書くなら、ON 句を JOIN の次の行にインデントして書くと、結合キーが揃って読みやすくなります。

まとめ

  • JOIN は何個でも縦に並べて連結できる
  • 別名 (AS) は 1-2 文字の小文字で短く統一する
  • INNER JOINLEFT JOIN を混ぜるときは「主軸テーブルが消えないか」確認する
  • 同名カラムは必ず テーブル別名.列名 で参照する
  • 結合キーにはインデックスを張ってパフォーマンス確保
  • 複数結合は「主軸 → 関連」の順で書くと読み手の頭に入りやすい

次のレッスン

次は 自己結合 です。SQLの自己結合を学び、同一テーブル内の関連データを操作するスキルを習得します。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. 複数結合 の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. 複数結合 とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

テーブル構造

schema.sql

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_idcustomer_nameproduct_namequantitysubtotal
1001田中キーボード18000
1001田中マウス25000
1002鈴木モニター135000
1003田中マウス37500

ヒント

query.sql
query.sql
学習モード
コードの実行結果
データベースを初期化中...