例えば、君が2つのテーブルを持っているとしよう:学生リストと、その学生が受講しているコースのリスト。全員がコースに登録しているわけじゃなくて、まだ何も選んでない学生もいる。全学生のリストを、コース未選択の人も含めて見たいとき、INNER JOINだとコース登録済みの人しか出てこない。じゃあ、他の学生はどうする?そこでLEFT JOINの出番だよ。
LEFT JOINは左側テーブル(クエリで最初に指定したやつ)の全行と右側テーブルの対応する行を返す。もし対応がなければ、右側テーブルのカラムにはNULLが入るんだ。
LEFT JOINの書き方
SELECT
テーブル1.カラム1,
テーブル1.カラム2,
テーブル2.カラム1,
テーブル2.カラム2
FROM
テーブル1 LEFT JOIN テーブル2
ON
テーブル1.共通カラム = テーブル2.共通カラム;
テーブル1— これが「左側」テーブル。テーブル2— これが「右側」テーブル。共通カラム— 結合に使う共通のカラム。
ざっくり例
もしstudentsテーブルがこんな感じだったら:
| student_id | name |
|---|---|
| 1 | Otto |
| 2 | Anna |
| 3 | Peter |
そしてenrollmentsテーブルがこう:
| enrollment_id | student_id | course |
|---|---|---|
| 1 | 1 | 数学 |
| 2 | 1 | 物理 |
| 3 | 2 | 生物学 |
このクエリを実行すると:
SELECT
students.name,
enrollments.course
FROM
students LEFT JOIN enrollments
ON
students.student_id = enrollments.student_id;
結果はこうなる:
| name | course |
|---|---|
| Otto | 数学 |
| Otto | 物理 |
| Anna | 生物学 |
| Peter | NULL |
見ての通り、結果には全学生が出てくる。たとえば、まだどのコースにも登録してないSergeyもいるよ。SergeyのcourseカラムはNULLになってる。
LEFT JOINの使い方例
例1:全学生とそのコースのリストを取得
やりたいこと:全学生と、もしコースに登録していればそのコースも一緒に表示したい。まだコース未選択の学生もちゃんと出したい。
さっきと同じクエリ:
SELECT
students.name,
enrollments.course
FROM
students LEFT JOIN enrollments
ON
students.student_id = enrollments.student_id;
結果:
| name | course |
|---|---|
| Otto | 数学 |
| Otto | 物理 |
| Anna | 生物学 |
| Peter | NULL |
これがLEFT JOINの典型的な使い方だね。
例2:商品とその売上を表示
例えば、君が2つのテーブルを持っているとしよう:
全部の商品が入ってるproductsテーブル:
| product_id | product_name |
|---|---|
| 1 | スマートフォン |
| 2 | タブレット |
| 3 | ノートパソコン |
売上データが入ってるsalesテーブル:
| sale_id | product_id | quantity |
|---|---|---|
| 1 | 1 | 5 |
| 2 | 1 | 3 |
| 3 | 2 | 2 |
今、全商品とその売上数を見たい。まだ売れてない商品も含めてね。
SELECT
products.product_name,
SUM(sales.quantity) AS total_sold
FROM
products LEFT JOIN sales
ON
products.product_id = sales.product_id
GROUP BY
products.product_name;
結果:
| product_name | total_sold |
|---|---|
| スマートフォン | 8 |
| タブレット | 2 |
| ノートパソコン | NULL |
LEFT JOINを使うときの注意点・ハマりポイント
いつもNULLでいいの?
時々、LEFT JOINで思わぬところにNULLが入ることがある。そんなときはCOALESCE()関数でNULLを分かりやすい値に置き換えよう。
SELECT
students.name,
COALESCE(enrollments.course, 'コース未選択') AS course
FROM
students LEFT JOIN enrollments
ON
students.student_id = enrollments.student_id;
結果:
| name | course |
|---|---|
| Otto | 数学 |
| Otto | 物理 |
| Anna | 生物学 |
| Peter | コース未選択 |
いらない重複
右側テーブルに重複データがあると、クエリ結果が思ったより多くなることがある。データをよく見て、重複がいらないならDISTINCTを使おう。
GO TO FULL VERSION