UNION と JOIN の違いとは?

カテゴリ:データベース編

UNION

UNION

UNION は同じ構造の2つの表のクエリ結果を結合します。(UNION するクエリ元は同じ表でも良いがクエリ結果が同じ構造でなければならない)

例えば次のような同じ構造を持つ2つの表、tb_1 と tb_2 があったとします。

mysql> SELECT name, count FROM tb_1;
+--------+-------+
| name   | count |
+--------+-------+
| apple  |     3 |
| orange |     5 |
| lemon  |     2 |
+--------+-------+
3 rows in set (0.00 sec)
mysql> SELECT name, count FROM tb_2;
+-------+-------+
| name  | count |
+-------+-------+
| lemon |     5 |
| apple |     3 |
| peach |     7 |
+-------+-------+
3 rows in set (0.00 sec)

この2つの表のクエリ結果を1つにまとめたい時、以下のように UNION を使用します。

単に UNION だけを指定した場合、重複行は省かれるため、両方の表に存在する行「name:apple count:3」は1行しか表示されていません。

mysql> SELECT name, count FROM tb_1 UNION SELECT name, count FROM tb_2;
+--------+-------+
| name   | count |
+--------+-------+
| apple  |     3 |
| orange |     5 |
| lemon  |     2 |
| lemon  |     5 |
| peach  |     7 |
+--------+-------+
5 rows in set (0.00 sec)

UNION ALL

UNION ALL を使用した場合は、重複行も含めて表示されます。以下の結果では重複する「name:apple count:3」の行が2行表示されていることがわかります。

mysql> SELECT name, count FROM tb_1 UNION ALL SELECT name, count FROM tb_2;
+--------+-------+
| name   | count |
+--------+-------+
| apple  |     3 |
| orange |     5 |
| lemon  |     2 |
| lemon  |     5 |
| apple  |     3 |
| peach  |     7 |
+--------+-------+
6 rows in set (0.00 sec)

name の数を合計して name ごとに表示するには、以下のように副問い合わせ(SQL文の中でSQL文を使用すること)の中で UNION ALL を使用します。

mysql> SELECT name, SUM(count) total FROM (SELECT name, count FROM tb_1 UNION ALL SELECT name, count FROM tb_2) AS tb_3 GROUP BY name;
+--------+-------+
| name   | total |
+--------+-------+
| apple  |     6 |
| orange |     5 |
| lemon  |     7 |
| peach  |     7 |
+--------+-------+
4 rows in set (0.00 sec)

JOIN

一方、JOIN は異なる構造の2つの表をあるカラムを基に結合します。

例えば以下のような構造の異なる2つの表があったとします。この2つの表は name_id という共通のカラムを持ち、tb_name では name_id と name は一意の値に紐づけされています。

mysql> SELECT * FROM tb_3;
+---------+-------+
| name_id | count |
+---------+-------+
|       1 |     3 |
|       2 |     5 |
|       3 |     2 |
+---------+-------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM tb_name;
+----+--------+
| id | name   |
+----+--------+
|  1 | apple  |
|  2 | orange |
|  3 | lemon  |
|  4 | peach  |
+----+--------+
4 rows in set (0.00 sec)

JOIN

このような場合に、JOIN を用いて2つの表を結合して tb_name の name と tb_3 の count を1つの表として表示できます。

JOIN は2つの表の条件に合致するすべての行を結合して表示します。これを内部結合といいます。

mysql> SELECT b.name, a.count FROM tb_3 a JOIN tb_name b ON a.name_id=b.id;
+--------+-------+
| name   | count |
+--------+-------+
| apple  |     3 |
| orange |     5 |
| lemon  |     2 |
+--------+-------+
3 rows in set (0.00 sec)

INNER JOIN (内部結合)

JOIN は INNER JOIN と同じです。つまり INNER JOIN を省略したものです。

mysql> SELECT b.name, a.count FROM tb_3 a INNER JOIN tb_name b ON a.name_id=b.id;
+--------+-------+
| name   | count |
+--------+-------+
| apple  |     3 |
| orange |     5 |
| lemon  |     2 |
+--------+-------+
3 rows in set (0.00 sec)

LEFT JOIN

LEFT JOIN を用いると左側の表(tb_3)を基準に、右側の表(tb_name)を結合します。このため、左側の表に対して左側の表に合致する右側の表の行のみが結合されます。一方の表を基準として結合することを外部結合といいます。

mysql> SELECT b.name, a.count FROM tb_3 a LEFT JOIN tb_name b ON a.name_id=b.id;
+--------+-------+
| name   | count |
+--------+-------+
| apple  |     3 |
| orange |     5 |
| lemon  |     2 |
+--------+-------+
3 rows in set (0.00 sec)

LEFT OUTER JOIN (左外部結合)

LEFT JOIN は LEFT OUTER JOIN と同じです。つまり LEFT JOIN は左外部結合であり、LEFT OUTER JOIN を省略したものです。

mysql> SELECT b.name, a.count FROM tb_3 a LEFT OUTER JOIN tb_name b ON a.name_id=b.id;
+--------+-------+
| name   | count |
+--------+-------+
| apple  |     3 |
| orange |     5 |
| lemon  |     2 |
+--------+-------+
3 rows in set (0.00 sec)

RIGHT JOIN

逆に RIGHT JOIN は右側の表(tb_name)を基準に、左側の表(tb_3)を結合します。このため、右側の表に対して右側の表に合致する左側の表の行のみが結合されます。以下の結果のように右側の表の行は左の表と条件に合致する行がない行(id:4)も含めて表示されています。(合致しないため値はNULLになります)

mysql> SELECT b.name, a.count FROM tb_3 a RIGHT JOIN tb_name b ON a.name_id=b.id;
+--------+-------+
| name   | count |
+--------+-------+
| apple  |     3 |
| orange |     5 |
| lemon  |     2 |
| peach  |  NULL |
+--------+-------+
4 rows in set (0.00 sec)

RIGHT OUTER JOIN (右外部結合)

RIGHT JOIN は RIGHT OUTER JOIN と同じです。つまり RIGHT JOIN は右外部結合であり、RIGHT OUTER JOIN を省略したものです。

mysql> SELECT b.name, a.count FROM tb_3 a RIGHT OUTER JOIN tb_name b ON a.name_id=b.id;
+--------+-------+
| name   | count |
+--------+-------+
| apple  |     3 |
| orange |     5 |
| lemon  |     2 |
| peach  |  NULL |
+--------+-------+
4 rows in set (0.00 sec)

FULL JOIN (完全結合)

FULL JOIN は2つの表のすべての行(条件に合致する行と合致しなかった行の両方)を結合して表示します。但し、MySQLでは使用できません。

FULL OUTER JOIN (完全外部結合)

FULL JOIN は FULL OUTER JOIN と同じです。つまり FULL OUTER JOIN を省略したものです。

LEFTとRIGHTについて

LEFT は JOIN の左側に指定した表、つまり FROM に指定した表を指します。一方、RIGHT は JOIN の右側に指定した表、つまり JOIN に指定した表を指します。

左内部結合や右内部結合は無いのか

そもそも内部結合は結合する両方の表のすべての行を表示するものであり、一方の表を基準にするわけではないため左内部結合や右内部結合はありません。

UNION と JOIN の組み合わせ

ここに tb_3 と同じ構造を持つテーブル tb_4 があったとします。

mysql> SELECT * FROM tb_4;
+---------+-------+
| name_id | count |
+---------+-------+
|       3 |     5 |
|       1 |     3 |
|       4 |     7 |
+---------+-------+
3 rows in set (0.00 sec)

tb_3 と tb_4 のクエリ結果を結合 (UNION) して、その結果に対して tb_name と左結合 (LEFT JOIN) することも可能です。

mysql> SELECT b.name, SUM(a.count) FROM (SELECT name_id, count FROM tb_3 UNION ALL SELECT name_id, count FROM tb_4) a LEFT JOIN tb_name b ON a.name_id=b.id GROUP BY b.name;
+--------+--------------+
| name   | SUM(a.count) |
+--------+--------------+
| apple  |            6 |
| orange |            5 |
| lemon  |            7 |
| peach  |            7 |
+--------+--------------+
4 rows in set (0.00 sec)

公開日時:2023年04月08日 03:25:33
最終更新日時:2023年04月08日 13:08:35

なお、レンタルサーバー選びで迷ったらこちらの記事で主要レンタルサーバーのプランと料金を比較していますので、是非参考にしてみてください。

データベース編に戻る

このページのトップに戻る