テーブル結合(JOIN)とは、 複数のテーブルを組み合わせてデータを取得する方法です。
JOINは
SELECT文で指定できる句の一つで、実際の開発現場では頻繁に使われます。むしろ、JOIN を使わずにデータを取得するケースのほうが少ないほどです。
JOIN にはいくつかの種類がありますが、特に
使用頻度が高いのは
LEFT JOIN
です。
他にも
CROSS JOINや
RIGHT JOINなどがありますが、利用する機会は少ないため、必要になったときに覚えれば問題ありません。
それでは、
LEFT JOINの仕組みを
実際の例を使って見ていきましょう。
以下がLEFT JOINの基本的なSQL構文です。
SELECT
A.列名1, A.列名2, B.列名3
FROM
テーブルA AS A
LEFT JOIN
テーブルB AS B
ON
A.共通カラム = B.共通カラム;
テーブルA(左のテーブル)のすべての行が返されます。
テーブルB(右のテーブル)に対応するデータがない場合は、
NULLが入ります。
たとえば、「顧客(customers)」テーブルと「注文(orders)」テーブルがあり、各顧客が過去に注文をしたかどうかを取得したい場合、以下のようにLEFT JOINを使用できます。
| customer_id | name |
|---|---|
| 1 | 田中 |
| 2 | 鈴木 |
| 3 | 佐藤 |
| order_id | customer_id | product |
|---|---|---|
| 101 | 1 | ノートPC |
| 102 | 2 | スマホ |
SELECT
customers.customer_id,
customers.name,
orders.product
FROM
customers
LEFT JOIN
orders
ON
customers.customer_id = orders.customer_id;
| customer_id | name | product |
|---|---|---|
| 1 | 田中 | ノートPC |
| 2 | 鈴木 | スマホ |
| 3 | 佐藤 | NULL |
この結果から、佐藤さん(customer_id=3)は注文履歴がないことが分かります。
INNER JOINと
LEFT JOINの違いに注意しましょう。
SELECT
customers.customer_id,
customers.name,
orders.product
FROM
customers
INNER JOIN
orders
ON
customers.customer_id = orders.customer_id;
| customer_id | name | product |
|---|---|---|
| 1 | 田中 | ノートPC |
| 2 | 鈴木 | スマホ |
INNER JOINでは、「一致するデータのみ」が返るため、注文がない佐藤さん(customer_id=3)のデータは含まれません。
→ LEFT JOINは、関連データがない場合でも左側のテーブルのデータを維持し、NULLを返すのが特徴です。
このようによく似ているため、LEFT JOINでなくINNER JOINを採用するエンジニアもいます。
LEFT JOINは1つのテーブルだけでなく、 複数のテーブルを結合することも可能です。というより実際、このような使われ方をされることの方が多いです。たとえば、顧客(customers)、注文(orders)、配送情報(shipments)の3つのテーブルを結合し、各顧客の注文と配送状況を取得するケースを考えます。
| customer_id | name |
|---|---|
| 1 | 田中 |
| 2 | 鈴木 |
| 3 | 佐藤 |
| order_id | customer_id | product |
|---|---|---|
| 101 | 1 | ノートPC |
| 102 | 2 | スマホ |
| shipment_id | order_id | status |
|---|---|---|
| 201 | 101 | 配送済み |
| 202 | 102 | 配送中 |
SELECT
customers.customer_id,
customers.name,
orders.product,
shipments.status
FROM
customers
LEFT JOIN
orders
ON
customers.customer_id = orders.customer_id
LEFT JOIN
shipments
ON
orders.order_id = shipments.order_id;
| customer_id | name | product | status |
|---|---|---|---|
| 1 | 田中 | ノートPC | 配送済み |
| 2 | 鈴木 | スマホ | 配送中 |
| 3 | 佐藤 | NULL | NULL |
このクエリでは、
NULLが入る
このように、複数のLEFT JOINを使うことで、必要なデータを組み合わせることができます。
以下のテーブル
employeesと
departmentsを元に、LEFT JOINを使用して全社員の部署情報を取得するSQLを作成してください。
employees(社員情報)
| employee_id | name | department_id |
|---|---|---|
| 1 | 田中 | 1 |
| 2 | 鈴木 | 2 |
| 3 | 佐藤 | NULL |
departments(部署情報)
| department_id | department_name |
|---|---|
| 1 | 営業部 |
| 2 | 開発部 |
期待される結果
| employee_id | name | department_name |
|---|---|---|
| 1 | 田中 | 営業部 |
| 2 | 鈴木 | 開発部 |
| 3 | 佐藤 | NULL |
LEFT JOINを使用すると、右側のテーブルに対応するデータがない場合
NULLになります。
employeesテーブルに所属部署がない社員(department_idがNULL)のみを取得するSQLを作成してください。
employeesテーブルと
departmentsテーブルを
INNER JOINを使って結合した場合、どのような結果になりますか?
LEFT JOINとの違いを説明してください。
次の
ordersテーブルと
shipmentsテーブルを
customersテーブルと結合し、各顧客の注文情報と配送状況を取得するSQLを作成してください。
customers(顧客情報)
| customer_id | name |
|---|---|
| 1 | 田中 |
| 2 | 鈴木 |
| 3 | 佐藤 |
orders(注文情報)
| order_id | customer_id | product |
|---|---|---|
| 101 | 1 | ノートPC |
| 102 | 2 | スマホ |
shipments(配送情報)
| shipment_id | order_id | status |
|---|---|---|
| 201 | 101 | 配送済み |
| 202 | 102 | 配送中 |
期待される結果
| customer_id | name | product | status |
|---|---|---|---|
| 1 | 田中 | ノートPC | 配送済み |
| 2 | 鈴木 | スマホ | 配送中 |
| 3 | 佐藤 | NULL | NULL |