【MySQL】外部結合(LEFT JOIN / RIGHT JOIN) - テーブル結合
MySQLの外部結合について解説します。
検証環境
外部結合
外部結合は“複数テーブルを繋げて1つの表データを作成すること”です。
各テーブルのカラムについて、値が同じレコード同士を繋げます。
内部結合と異なり、結合しなかったレコードも表示されます。
次のshops
テーブルとitems
テーブルで具体例を示します。
/* shopsテーブル */
+----+--------------+
| id | name |
+----+--------------+
| 1 | Fruits Shop |
| 2 | Food Shop |
| 3 | Dessert Shop |
+----+--------------+
/* itemsテーブル */
+----+-----------+-------+-------+---------+
| id | name | price | stock | shop_id |
+----+-----------+-------+-------+---------+
| 1 | Apple | 200 | 10 | 1 |
| 2 | Orange | 150 | 3 | 1 |
| 3 | Pineapple | 1100 | 3 | 2 |
| 4 | Grapes | 3500 | 1 | 2 |
+----+-----------+-------+-------+---------+
items
テーブルはshop_id
カラムでshops
テーブルのid
カラムの値を保持します。
この2カラムで外部結合した結果は次の表です。
+----+--------------+------+-----------+-------+-------+---------+
| id | name | id | name | price | stock | shop_id |
+----+--------------+------+-----------+-------+-------+---------+
| 1 | Fruits Shop | 1 | Apple | 200 | 10 | 1 |
| 1 | Fruits Shop | 2 | Orange | 150 | 3 | 1 |
| 2 | Food Shop | 3 | Pineapple | 1100 | 3 | 2 |
| 2 | Food Shop | 4 | Grapes | 3500 | 1 | 2 |
| 3 | Dessert Shop | NULL | NULL | NULL | NULL | NULL |
+----+--------------+------+-----------+-------+-------+---------+
各テーブルのレコードが2カラムを基点に結合されています。
shops
テーブルのid
が3のレコードは、items
テーブルのshop_id
カラムに存在しないため、items
テーブルのカラム値はNULL
が表示されます。
また、外部結合には左外部結合と右外部結合があります。
2つのテーブルを横に並べたとき、左を軸にするのが左外部結合、右を軸にするのが右外部結合です。
上記具体例はshops
テーブル(左)、items
テーブル(右)とした時、左外部結合になります。
LEFT JOIN
MySQLで左外部結合を実現するにはLEFT JOIN句を使用します。
基本構文
SELECT 表示カラム FROM テーブルA LEFT JOIN テーブルB ON テーブルA.カラム = テーブルB.カラム
LEFT JOIN句はSELECT文と合わせて使用します。
LEFT JOIN テーブルB ON テーブルA.カラム = テーブルB.カラム
がLEFT JOIN句の部分です。
基本的には内部結合のINNER JOIN句と同様で、SELECT文のテーブルA
に対して外部結合するテーブルB
と、結合の基点となる各カラムをテーブルA.カラム
、テーブルB.カラム
の形式で記述します。
サンプル
mysql> SELECT * FROM shops;
+----+--------------+
| id | name |
+----+--------------+
| 1 | Fruits Shop |
| 2 | Food Shop |
| 3 | Dessert Shop |
+----+--------------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM items;
+----+-----------+-------+-------+---------+
| id | name | price | stock | shop_id |
+----+-----------+-------+-------+---------+
| 1 | Apple | 200 | 10 | 1 |
| 2 | Orange | 150 | 3 | 1 |
| 3 | Pineapple | 1100 | 3 | 2 |
| 4 | Grapes | 3500 | 1 | 2 |
+----+-----------+-------+-------+---------+
4 rows in set (0.00 sec)
mysql> SELECT * FROM shops
___ih_hl_start
-> LEFT JOIN items ON shops.id = items.shop_id;
___ih_hl_end
+----+--------------+------+-----------+-------+-------+---------+
| id | name | id | name | price | stock | shop_id |
+----+--------------+------+-----------+-------+-------+---------+
| 1 | Fruits Shop | 1 | Apple | 200 | 10 | 1 |
| 1 | Fruits Shop | 2 | Orange | 150 | 3 | 1 |
| 2 | Food Shop | 3 | Pineapple | 1100 | 3 | 2 |
| 2 | Food Shop | 4 | Grapes | 3500 | 1 | 2 |
| 3 | Dessert Shop | NULL | NULL | NULL | NULL | NULL |
+----+--------------+------+-----------+-------+-------+---------+
5 rows in set (0.00 sec)
23行目が左外部結合(LEFT JOIN句)の部分です。
shops
テーブル(左)のid
カラムに対して、items
テーブル(右)のshop_id
カラムの値が同じレコードを結合しています。
上記サンプルでは*
によって全てのカラムを表示していますが、通常のSELECT文と同様に任意のカラムのみ表示することも可能です。
2つのテーブルでカラム名が重複している場合は、どちらのテーブルのカラムか分かるようにテーブル名とカラム名をドット(.
)で繋げ、テーブル名.カラム名
のように明示的に記述します。
mysql> SELECT shops.name, items.name, price, stock FROM shops
-> LEFT JOIN items ON shops.id = items.shop_id;
+--------------+-----------+-------+-------+
| name | name | price | stock |
+--------------+-----------+-------+-------+
| Fruits Shop | Apple | 200 | 10 |
| Fruits Shop | Orange | 150 | 3 |
| Food Shop | Pineapple | 1100 | 3 |
| Food Shop | Grapes | 3500 | 1 |
| Dessert Shop | NULL | NULL | NULL |
+--------------+-----------+-------+-------+
5 rows in set (0.01 sec)
RIGHT JOIN
MySQLで右外部結合を実現するにはRIGHT JOIN句を使用します。
基本構文
SELECT 表示カラム FROM テーブルA RIGHT JOIN テーブルB ON テーブルA.カラム = テーブルB.カラム
RIGHT JOIN句はSELECT文と合わせて使用します。
基本的にはLEFT JOIN句と同じで、RIGHT
かLEFT
の違いになります。
サンプル
mysql> SELECT * FROM shops;
+----+--------------+
| id | name |
+----+--------------+
| 1 | Fruits Shop |
| 2 | Food Shop |
| 3 | Dessert Shop |
+----+--------------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM items;
+----+-----------+-------+-------+---------+
| id | name | price | stock | shop_id |
+----+-----------+-------+-------+---------+
| 1 | Apple | 200 | 10 | 1 |
| 2 | Orange | 150 | 3 | 1 |
| 3 | Pineapple | 1100 | 3 | 2 |
| 4 | Grapes | 3500 | 1 | 2 |
+----+-----------+-------+-------+---------+
4 rows in set (0.00 sec)
mysql> SELECT * FROM shops
___ih_hl_start
-> RIGHT JOIN items ON shops.id = items.shop_id;
___ih_hl_end
+------+-------------+----+-----------+-------+-------+---------+
| id | name | id | name | price | stock | shop_id |
+------+-------------+----+-----------+-------+-------+---------+
| 1 | Fruits Shop | 1 | Apple | 200 | 10 | 1 |
| 1 | Fruits Shop | 2 | Orange | 150 | 3 | 1 |
| 2 | Food Shop | 3 | Pineapple | 1100 | 3 | 2 |
| 2 | Food Shop | 4 | Grapes | 3500 | 1 | 2 |
+------+-------------+----+-----------+-------+-------+---------+
4 rows in set (0.00 sec)
23行目が右外部結合(RIGHT JOIN句)の部分です。
items
テーブル(右)のshop_id
カラムを基準にshops
テーブル(左)のid
カラムの値が同じレコードを結合しています。
上記サンプルでは*
によって全てのカラムを表示していますが、通常のSELECT文と同様に任意のカラムのみ表示することも可能です。
2つのテーブルでカラム名が重複している場合もLEFT JOIN句と同様に明示的に記述します。
mysql> SELECT shops.name, items.name, price, stock FROM shops
-> RIGHT JOIN items ON shops.id = items.shop_id;
+-------------+-----------+-------+-------+
| name | name | price | stock |
+-------------+-----------+-------+-------+
| Fruits Shop | Apple | 200 | 10 |
| Fruits Shop | Orange | 150 | 3 |
| Food Shop | Pineapple | 1100 | 3 |
| Food Shop | Grapes | 3500 | 1 |
+-------------+-----------+-------+-------+
4 rows in set (0.00 sec)