SQLでSELECT文を書いていると、複数のテーブルをがっちゃんこしたい!と思う時があるでしょう。これをSQLではテーブル結合と言います。
テーブル結合ができるようになれば、分析の幅が大きく広がります。むしろ、テーブル結合なしには分析ができないと言っても過言ではないくらい重要です。
本記事ではテーブル結合とは何か?から始まり、結合の種類や使い方について詳しく解説しています。
目次
SQLのテーブル結合とは
SQLのテーブル結合とは、文字通り複数のテーブルを結合することを指します。
これだけではイメージが付きにくいので図解を交えて解説します。
例えば、ユーザー情報を管理するusersテーブルと、注文情報を管理するorderテーブルが存在したとします。

ここからユーザーが注文した商品を集計したい時どうすればいいでしょう。
1つ考えられるやり方として、usersテーブルとorderテーブルの情報をそれぞれ抽出して、エクセルにインポートして照合する方法です。

しかし、毎回これをするのは面倒ですし何よりも時間がかかります。
できることならSQL上で統合を行なって分析を行いたいものです。これを実現するのが「SQLのテーブル結合」です。
テーブル結合を使えばエクセルで行っていた統合作業をSQL上で行うことができます。

usersテーブルのIDとorderテーブルのuser_idは一致するため、この2つを起点としてテーブルを結合することができます。
今回はid情報を元に結合を行いましたが、複数のテーブルで同じ値を扱うカラムが存在すればid以外でもテーブル結合は可能です。
例えば、テーブルAとテーブルBのどちらにもemailの情報が存在していれば、emailを起点としてテーブル結合をするといった具合です。
SQLで使える結合は5種類
テーブル結合とは何かを説明してきましたが、実は結合の種類は一つではありません。
下記の5種類が存在します。
| 結合の種類 | イメージ図 | 概要 |
|---|---|---|
| 1. 内部結合 (INNER JOIN) | ![]() | 値が一致したレコードだけを結合 |
| 2. 外部結合 (LEFT OUTER JOIN) | ![]() | 左(A)の全てのレコードを取得 + 左(A)と値が一致した右(B)のレコードを結合 |
| 3. 外部結合 (RIGHT OUTER JOIN) | ![]() | 右(B)の全てのレコードを取得 + 右(B)と一致した左(A)のレコードを結合 |
| 4. 外部結合 (FULL OUTER JOIN) | ![]() | 左(A)と右(B)の全てのレコードを取得 |
| 5. クロス結合 (CROSS JOIN) | ![]() | テーブルの全ての組み合わせを取得 |
それでは、具体例を交えて一つずつ解説していきます。
サンプルデータ
下記のとおり、employeeテーブルとdepartmentテーブルを用意します。
employeeテーブルは従業員情報を管理し、departmentテーブルは配属部門を管理しています。
employeeテーブル
| id | name | department_id |
|---|---|---|
| 1 | 山田 | 3 |
| 2 | 鈴木 | 4 |
| 3 | 佐藤 | 1 |
| 4 | 佐々木 | 6 |
| 5 | 丸山 | 1 |
departmentテーブル
| id | name |
|---|---|
| 1 | 営業部 |
| 2 | 人事部 |
| 3 | 企画部 |
| 4 | 経理部 |
| 5 | 開発部 |
SQLの内部結合「INNER JOIN」
内部結合は、それぞれのテーブルで指定した値が一致したレコードだけを結合します。実務で最も使うのがINNER JOINを使った内部結合なので、必ず押さえておきましょう。

INNER(内部)というだけあって、
テーブルAとテーブルBの一致したレコードのみを取得
今回の場合、employeeテーブルのdepartment_idとdepartmentテーブルのidが同じ意味を持つカラムになっているため、この2つを起点として結合を行います。

結果、department_idとidカラムそれぞれの値が一致したレコードだけが結合されます。これが内部結合INNER JOINです。
INNER JOINの基本構文が下記です。
SELECT カラム名
FROM テーブル名1
INNER JOIN テーブル名2
ON 結合の条件;INNER JOINの後に結合するテーブル名を記載し、ONの後にテーブル名1とテーブル名2を結合するための条件を記載します。
検索クエリ
employeeテーブルとdepartmentテーブルを内部結合して取得する
SELECT *
FROM employee
INNER JOIN department
ON employee.department_id = department.id;考え方は下記です。
- SELECT文でemployeeテーブルから全ての情報を取得する命令を出す
INNER JOINでdepartmentテーブルをemployeeテーブルに結合する命令を出すONの後にemployee.department_id = department.idと書くことで、employeeテーブルとdepartmentテーブルを結合するための条件を指定
実行結果
| id | name | department_id | id | name |
|---|---|---|---|---|
| 3 | 佐藤 | 1 | 1 | 営業部 |
| 1 | 山田 | 3 | 3 | 企画部 |
| 2 | 鈴木 | 4 | 4 | 経理部 |
| 5 | 丸山 | 1 | 1 | 営業部 |
department_idとidが結合された上でレコードを取得することができました。両方のカラムに存在する値だけが残っていることが分かります。
また、テーブルを結合すると同じ名前のカラムが複数できるので、AS句を使って別名をつけると分かりやすくなります。
内部結合INNER JOINについては下記でも詳しくまとめています。
SQLの外部結合「OUTER JOIN」
外部結合は、内部結合のように2つのテーブルで指定したカラムの値が一致するレコードに加えて、どちらかのテーブルにしか存在しないレコードも取得します。
そして、外部結合には下記の3種類が存在します。
- LEFT OUTER JOIN
- RIGHT OUTER JOIN
- FULL OUTER JOIN
それぞれ順に見ていきましょう。
LEFT OUTER JOIN

左側のテーブル全て
+
テーブルAとテーブルBの一致したレコード
今回の場合、テーブルAをemployeeテーブルとすると、department_idが結合の起点になります。
下記の図のようにdepartment_idのレコードは全て取得した上で、テーブルBのdepartmentテーブルのidが一致するレコードを取得します。

そしてポイントが、結合先であるdepartmentテーブルに存在しない値がある場合にはNULLが割り当てられるということです。department_idが6に一致する値はdepartmentテーブルには存在しないためNULLとなっています。
あくまで左側のテーブルが起点となるのが左外部結合のLEFT OUTER JOINです。
LEFT OUTER JOINの基本構文が下記です。
SELECT カラム名
FROM テーブル名1
LEFT OUTER JOIN テーブル名2
ON 結合の条件;テーブル名1に結合元(起点)となるテーブルを指定し、テーブル名2に結合先のテーブルを指定します。
検索クエリ
employeeテーブルにdepartmentテーブルを左外部結合(LEFT OUTER JOIN)して取得する
SELECT *
FROM employee
LEFT OUTER JOIN department
ON employee.department_id = department.id;考え方は下記です。
- SELECT文でemployeeテーブルから全ての情報を取得する命令を出す
LEFT OUTER JOINでemployeeテーブルを起点として、departmentテーブルを結合する命令を出すONの後にemployee.department_id = department.idと書くことで、employeeテーブルとdepartmentテーブルを結合するための条件を指定
また、LEFT OUTER JOINはLEFT JOINと省略して書くことも可能です。
実行結果
| id | name | department_id | id | name |
|---|---|---|---|---|
| 3 | 佐藤 | 1 | 1 | 営業部 |
| 1 | 山田 | 3 | 3 | 企画部 |
| 2 | 鈴木 | 4 | 4 | 経理部 |
| 4 | 佐々木 | 6 | NULL | NULL |
| 5 | 丸山 | 1 | 1 | 営業部 |
employeeテーブルを起点としてdepartmentテーブルを結合することができました。departmentテーブルはidが6の値は存在しないため、代わりにNULLが割り当てられています。
LEFT OUTER JOINについては下記の記事でも詳しくまとめています。
RIGHT OUTER JOIN

右側のテーブル全て
+
テーブルAとテーブルBの一致したレコード
RIGHT OUTER JOINはLEFT OUTER JOINの真逆と覚えておけばOKです。右側のテーブルに対して左側のテーブルを結合します。今回の場合は、departmentテーブルに対してemployeeテーブルを結合することになります。
下記の図のようにdepartmentテーブルのidは全て取得した上で、employeeテーブルのdepartment_idが一致するレコードを取得します。

結合元のdepartmentテーブルのidに存在して、結合先であるemployeeテーブルのdepartment_idに存在しない値があれば、NULLが割り当てられます。
あくまで右側のテーブルが起点となるのが右外部結合のRIGHT OUTER JOINです。
RIGHT OUTER JOINの基本構文が下記です。
SELECT カラム名
FROM テーブル名1
RIGHT OUTER JOIN テーブル名2
ON 結合の条件;検索クエリ
employeeテーブルにdepartmentテーブルを右外部結合(RIGHT OUTER JOIN)して取得する
SELECT *
FROM employee
RIGHT OUTER JOIN department
ON employee.department_id = department.id;また、RIGHT OUTER JOINはRIGHT JOINと省略して書くことも可能です。
実行結果
| id | name | department_id | id | name |
|---|---|---|---|---|
| 1 | 山田 | 3 | 3 | 企画部 |
| 2 | 鈴木 | 4 | 4 | 経理部 |
| 3 | 佐藤 | 1 | 1 | 営業部 |
| 5 | 丸山 | 1 | 1 | 営業部 |
| NULL | NULL | NULL | 2 | 人事部 |
| NULL | NULL | NULL | 5 | 開発部 |
departmentテーブルを起点にしてemployeeテーブルを結合することができました。
departmentテーブルのidが2と5の値はemployeeテーブルは存在しないため、NULLが保存されています。
FULL OUTER JOIN

テーブルAとテーブルBの全て
FULL OUTER JOINは両者総取りです。
下記3点に該当するレコードを取得します。
- テーブルAとテーブルBのカラムの値が一致するレコード
- テーブルAには存在して、テーブルBのカラムには値が存在しないレコード
- テーブルAには存在せず、テーブルBのカラムには値が存在するレコード

どちらか一つのテーブルにしか存在しない値がある場合は、もう一方のカラムにはNULLが保存されます。
※FULL OUTER JOINはMySQLなど一部のデータベースでは対応していないためご注意ください。
FULL OUTER JOINの基本構文は下記です。
SELECT カラム名
FROM テーブル名1
FULL OUTER JOIN テーブル名2
ON 結合の条件;検索クエリ
employeeテーブルにdepartmentテーブルを完全外部結合(FULL OUTER JOIN)して取得する
SELECT *
FROM employee
FULL OUTER JOIN department
ON employee.department_id = department.id;また、FULL OUTER JOINはFULL JOINと省略して書くことも可能です。
実行結果
| id | name | department_id | id | name |
|---|---|---|---|---|
| 1 | 山田 | 3 | 3 | 企画部 |
| 2 | 鈴木 | 4 | 4 | 経理部 |
| 3 | 佐藤 | 1 | 1 | 営業部 |
| 4 | 佐々木 | 6 | NULL | NULL |
| 5 | 丸山 | 1 | 1 | 営業部 |
| NULL | NULL | NULL | 2 | 人事部 |
| NULL | NULL | NULL | 5 | 開発部 |
employeeテーブルとdepartmentテーブルを完全外部結合することができました。
employeeテーブルのdepartment_idが6の値はdepartmentテーブルには存在しないためNULLが保存されています。一方で、departmentテーブルのidが2と5の値はemployeeテーブルには存在しないため、NULLが保存されています。
このように、LEFT OUTER JOINとRIGHT OUTER JOINを足し合わせたものがFULL OUTER JOINと覚えておきましょう。
SQLのクロス結合「CROSS JOIN」
最後に、クロス結合について見ていきます。あまり実践で使うことは多くないので、ざっくり把握でもOKです。

テーブルAとテーブルBの全ての組み合わせ
クロス結合は、値の一致などは特に考えず、全てのレコードの組み合わせを取得する結合方法です。よって、実行結果のレコード数は膨大になります。
CROSS JOINの基本構文が下記です。
SELECT カラム名
FROM テーブル名1
CROSS JOIN テーブル名2;全てのレコードの組み合わせなので、他のJOIN句の時のようにONで条件指定をする必要がありません。
検索クエリ
SELECT *
FROM employee
CROSS JOIN department;実行結果
| id | name | department_id | id | name |
|---|---|---|---|---|
| 1 | 山田 | 3 | 1 | 営業部 |
| 2 | 鈴木 | 4 | 1 | 営業部 |
| 3 | 佐藤 | 1 | 1 | 営業部 |
| 4 | 佐々木 | 6 | 1 | 営業部 |
| 5 | 丸山 | 1 | 1 | 営業部 |
| 1 | 山田 | 3 | 2 | 人事部 |
| . . . | . . . | . . . | . . . | . . . |
右2列を見てみると、全てidが1の営業部の情報になっています。まずは、departmentテーブルのidが1を起点にしてemployeeテーブルの全ての組み合わせを取得しているのです。
これが、2の人事部の場合、3の企画部の場合、…という形で全パターンを取得してきます。
実践でよく使うのはINNER JOINとLEFT OUTER JOIN
ここまで、5種類の結合を説明してきましたが、実際のデータ分析でよく使うのはINNER JOINとLEFT OUTER JOINです。
INNER JOINの使いどころ
テーブルを組み合わせて表示したい時に有効なので、実践で最も使われる結合です。
例えば、従業員がどの部署に所属しているかを把握したい時に、従業員を管理するテーブルと部署を管理するテーブルをINNER JOINを使って結合することで、一覧を取得できます。
LEFT OUTER JOINの使いどころ
一つの情報を元に、全てのパターンを炙り出したい時に有効です。
例えば、ユーザーに一斉にアンケート回答をお願いしたとします。アンケート結果を分析するために、アンケートを管理するテーブルを起点にユーザーを管理するテーブルをLEFT OUTER JOINすることで、アンケートに回答していないユーザーにはNULLが保存されます。
誰がアンケートに回答していないか一目瞭然ということです。
この2つの結合方法については、必要になった時すぐに使えるように習得しておくことをおすすめします。
内容のまとめ
- SQLのテーブル結合とは、文字通り複数のテーブルを結合すること
- SQLで使える結合は5種類存在する
- 内部結合の
INNER JOINは、テーブルAとテーブルBのカラムの値が一致するレコードのみを取得する - 外部結合には、左外部結合の
LEFT OUTER JOIN、右外部結合のRIGHT OUTER JOIN、完全外部結合のFULL OUTER JOINの3種類がある - 左外部結合の
LEFT OUTER JOINは、テーブルAのレコードを全て取得した上で、テーブルBのカラムの値が一致するレコードも取得する - 右外部結合の
RIGHT OUTER JOINは、テーブルBのレコードを全て取得した上で、テーブルAのカラムの値が一致するレコードも取得する - 完全外部結合の
FULL OUTER JOINは、テーブルA・テーブルBそれぞれのレコードを全て取得した上で、テーブルAとテーブルBのカラムの値が一致するレコードも取得する - 外部結合の3つはそれぞれ
OUTERを省略することができる - クロス結合の
CROSS JOINはテーブルAとテーブルBの全てのレコードの組み合わせを取得するため、実行結果のデータ量が膨大になる - 実践でよく使う結合方法は、
INNER JOINとLEFT OUTER JOINの2つ


