SQLのINNER JOINとは?2つの表を結ぶ基本を実行結果で解説
INNER JOINは、2つの表から条件に合う行同士を結び付ける構文です。たとえば、注文の表に顧客名がなくても、顧客の表と結ぶと「誰の注文か」を表示できます。まずは小さな2つの表で、どの行がつながるかを見てみましょう。
例で使う表
このページでは、次の顧客3件と注文3件を使います。ordersのcustomer_idは、注文した顧客の番号です。注文101と102は顧客1の青木商店、注文103は顧客2の北野物産に対応します。顧客3の中央商事には注文がありません。
| id(顧客ID) | name(顧客名) |
|---|---|
| 1 | 青木商店 |
| 2 | 北野物産 |
| 3 | 中央商事 |
| id(注文ID) | customer_id(注文した顧客のID) | amount(金額) |
|---|---|---|
| 101 | 1 | 12000 |
| 102 | 1 | 8000 |
| 103 | 2 | 25000 |
INNER JOINの基本構文
SELECT customers.name, orders.id, orders.amount
FROM customers
INNER JOIN orders
ON customers.id = orders.customer_id
ORDER BY orders.id;INNER JOINで注文に顧客名を付ける
やりたいことは、顧客名・注文ID・金額を同じ行に並べることです。FROM customersで顧客の表を指定し、INNER JOIN ordersで注文の表を結びます。ON customers.id = orders.customer_idは「顧客IDが同じ行同士を組み合わせる」という条件です。SELECTには、結果に表示したい列を書きます。
SELECT customers.name, orders.id, orders.amount
FROM customers
INNER JOIN orders
ON customers.id = orders.customer_id
ORDER BY orders.id;| name | id | amount |
|---|---|---|
| 青木商店 | 101 | 12000 |
| 青木商店 | 102 | 8000 |
| 北野物産 | 103 | 25000 |
ONでどの行が結び付いたかを確かめる
青木商店のidは1です。注文101と102もcustomer_idが1なので、それぞれ青木商店と結び付きます。下のSQLでは比較した2つのIDも表示しています。customers.idは「顧客の表のid」、orders.idは「注文の表のid」です。同じidという列名でも、意味が違うので表の名前を付けて区別します。
SELECT customers.id, customers.name,
orders.customer_id, orders.amount
FROM customers
INNER JOIN orders
ON customers.id = orders.customer_id
ORDER BY orders.id;| id | name | customer_id | amount |
|---|---|---|---|
| 1 | 青木商店 | 1 | 12000 |
| 1 | 青木商店 | 1 | 8000 |
| 2 | 北野物産 | 2 | 25000 |
同じ顧客名が2行出るのはなぜ?
青木商店には注文が2件あるので、結果にも青木商店が2行出ます。それぞれ注文101と注文102を表しており、同じ注文が二重に表示されたわけではありません。INNER JOINは条件に合う組み合わせをすべて返します。顧客1件につき結果も1行になるとは限りません。
SELECT customers.name, orders.id, orders.amount
FROM customers
INNER JOIN orders
ON customers.id = orders.customer_id
WHERE customers.id = 1
ORDER BY orders.id;| name | id | amount |
|---|---|---|
| 青木商店 | 101 | 12000 |
| 青木商店 | 102 | 8000 |
一致する注文がない顧客は結果に出ない
中央商事のidは3ですが、ordersにはcustomer_idが3の注文がありません。結び付く相手がないため、最初の結果表に中央商事は出てきません。次のSQLで中央商事だけを指定しても、結果は0行です。元の顧客データが削除されるわけではありません。
SELECT customers.name, orders.id, orders.amount
FROM customers
INNER JOIN orders
ON customers.id = orders.customer_id
WHERE customers.id = 3;| name | id | amount |
|---|
結果は0行です。
慣れたらASで表の名前を短くする
ここまでのcustomersをc、ordersをoと短く書くこともできます。FROM customers AS cと書くと、このSQLの中ではcがcustomersの別名になります。下のSQLは最初のSQLと同じ結果です。まずは省略しない形で理解してから、別名を使うと読みやすくなります。
SELECT c.name, o.id, o.amount
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id
ORDER BY o.id;| name | id | amount |
|---|---|---|
| 青木商店 | 101 | 12000 |
| 青木商店 | 102 | 8000 |
| 北野物産 | 103 | 25000 |
実際に1問解いてみる
INNER JOIN・ON
注文に対応する顧客を結び、注文id、顧客名、注文額をこの順で取得してください。行順は問いません。
テーブル
読み込み中…
実行結果
関連構文
INNER JOINについてよくある質問
- JOINとINNER JOINは同じですか?
- はい。PostgreSQLではINNERを省略してJOINと書いても同じ意味です。このページでは結合の種類が分かるようにINNER JOINと書いています。
- ONでは同じ名前の列を指定する必要がありますか?
- いいえ。この例ではcustomers.idとorders.customer_idのように、名前が違っていても同じ顧客を表すIDを比較します。列名が同じかどうかではなく、何の値かを確認して結びます。
参考文献
内容はPostgreSQL公式ドキュメントを参照し、初めて学ぶ人向けに日本語で整理しています。
- PostgreSQL公式:テーブルの結合 — 結合条件、列の指定、別名の基本
- PostgreSQL公式:結合テーブル — INNER JOINとLEFT JOIN、ONとWHEREの仕様