言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

  1. トップページ
  2. SQL辞典
  3. INNER JOIN

INNER JOIN

対応: SQL-92(1992)

2つのテーブルを結合し、両方に一致する行のみを取得するSQL文です。最もよく使われる結合方法です。

構文

『INNER JOIN』で2つのテーブルを結合します。

SELECT column FROM table1
INNER JOIN table2 ON table1.join_column = table2.join_column;

『INNER』は省略可能です(『JOIN』のみでも同じ動作です)。

SELECT column FROM table1
JOIN table2 ON table1.join_column = table2.join_column;

『WHERE』句を使った結合(同じ意味)。

SELECT column FROM table1, table2
WHERE table1.join_column = table2.join_column;

構文一覧

構文概要
INNER JOIN table2 ON 条件両テーブルで ON の条件を満たす行のみを結合して取得します。どちらか一方に存在しない行は結果に含まれません。
JOIN table2 ON 条件INNER JOIN の省略形です。動作は同じです。
テーブル名 AS エイリアステーブルに短い別名を付けることができます。複数テーブルを扱う場合に記述を簡潔にできます。

サンプルで使用するテーブル

以下のサンプルコードでは、次の2つのテーブルを使用します。

CREATE TABLE departments (
    id INT PRIMARY KEY,
    department_name VARCHAR(50)
);
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    department_id INT,
    salary INT
);

INSERT INTO departments VALUES (1, '未来ガジェット研究所'), (2, 'ヴィクトル・コンドリア大学');
INSERT INTO employees VALUES
(1, '岡部倫太郎', 1, 300000), (2, '牧瀬紅莉栖', 2, 380000),
(3, '椎名まゆり', 1, 280000), (4, '橋田至', 1, 320000);

テーブルの内容を確認します。

SELECT * FROM employees;
+----+--------------+---------------+--------+
| id | name         | department_id | salary |
+----+--------------+---------------+--------+
|  1 | 岡部倫太郎   |             1 | 300000 |
|  2 | 牧瀬紅莉栖   |             2 | 380000 |
|  3 | 椎名まゆり   |             1 | 280000 |
|  4 | 橋田至       |             1 | 320000 |
+----+--------------+---------------+--------+
4 rows in set
SELECT * FROM departments;
+----+------------------------------+
| id | department_name              |
+----+------------------------------+
|  1 | 未来ガジェット研究所         |
|  2 | ヴィクトル・コンドリア大学   |
+----+------------------------------+
2 rows in set

サンプルコード

社員テーブルと部署テーブルを結合して、部署名とともに社員一覧を取得します。

employees id name department_id salary 1 岡部倫太郎 1 300000 2 牧瀬紅莉栖 2 380000 3 椎名まゆり 1 280000 4 橋田至 1 320000 4 rows in set

departments id department_name 1 未来ガジェット研究所 2 ヴィクトル・コンドリア大学 2 rows in set

社員テーブルと部署テーブルを結合して、部署名とともに社員一覧を取得します。

SELECT e.name, d.department_name, e.salary
FROM employees AS e
INNER JOIN departments AS d ON e.department_id = d.id;
+------------+------------------------------+--------+
| name       | department_name              | salary |
+------------+------------------------------+--------+
| 岡部倫太郎 | 未来ガジェット研究所         | 300000 |
| 牧瀬紅莉栖 | ヴィクトル・コンドリア大学   | 380000 |
| 椎名まゆり | 未来ガジェット研究所         | 280000 |
| 橋田至     | 未来ガジェット研究所         | 320000 |
+------------+------------------------------+--------+
4 rows in set

社員テーブルと部署テーブルを結合して、給与30万以上の社員を部署名とともに取得します。

SELECT e.name, d.department_name, e.salary
FROM employees AS e
INNER JOIN departments AS d ON e.department_id = d.id
WHERE e.salary >= 300000
ORDER BY e.salary DESC;
+------------+------------------------------+--------+
| name       | department_name              | salary |
+------------+------------------------------+--------+
| 牧瀬紅莉栖 | ヴィクトル・コンドリア大学   | 380000 |
| 橋田至     | 未来ガジェット研究所         | 320000 |
| 岡部倫太郎 | 未来ガジェット研究所         | 300000 |
+------------+------------------------------+--------+
3 rows in set

部署ごとの最高給与を社員テーブルと部署テーブルを結合して取得します(GROUP BY の応用)。

SELECT d.department_name, MAX(e.salary) AS max_salary
FROM employees AS e
INNER JOIN departments AS d ON e.department_id = d.id
GROUP BY d.department_name;
+------------------------------+------------+
| department_name              | max_salary |
+------------------------------+------------+
| 未来ガジェット研究所         |     320000 |
| ヴィクトル・コンドリア大学   |     380000 |
+------------------------------+------------+
2 rows in set

『WHERE』句の絞り込みと組み合わせます。

SELECT e.name, d.department_name
FROM employees AS e
INNER JOIN departments AS d ON e.department_id = d.id
WHERE d.department_name = '未来ガジェット研究所';
+------------+----------------------+
| name       | department_name      |
+------------+----------------------+
| 岡部倫太郎 | 未来ガジェット研究所 |
| 椎名まゆり | 未来ガジェット研究所 |
| 橋田至     | 未来ガジェット研究所 |
+------------+----------------------+
3 rows in set

INNER / LEFT / RIGHT / FULL JOIN の比較

結合の種類によって、一致しない行の扱いが変わります。

種類一致する行左テーブルのみ右テーブルのみ用途
INNER JOIN含む除外除外両テーブルで一致するデータだけ必要な場合
LEFT JOIN含む含む(右はNULL)除外左テーブルの全行を残したい場合(ユーザー一覧+注文履歴など)
RIGHT JOIN含む除外含む(左はNULL)右テーブルの全行を残したい場合(LEFT JOINで書き直せることが多い)
FULL JOIN含む含む(右はNULL)含む(左はNULL)両方のテーブルを全行残したい場合(MySQL非対応)

以下は、部署テーブルに対応するレコードがない社員5(department_id=99)がいる場合の比較です。

-- INNER JOIN: 部署が存在する社員だけを返す
SELECT e.name, d.department_name
FROM employees AS e
INNER JOIN departments AS d ON e.department_id = d.id;
-- 社員5(department_id=99)は結果に含まれない

-- LEFT JOIN: 全社員を返し、部署がない場合は NULL を表示する
SELECT e.name, d.department_name
FROM employees AS e
LEFT JOIN departments AS d ON e.department_id = d.id;
-- 社員5の department_name は NULL になる

-- RIGHT JOIN: 全部署を返し、社員がいない部署も含める
SELECT e.name, d.department_name
FROM employees AS e
RIGHT JOIN departments AS d ON e.department_id = d.id;
-- 社員のいない部署は name が NULL になる

「LEFT JOINして一致しないレコードだけを取得する」パターンは、NOT IN より高速なことが多く実務でよく使われます。

-- 部署に所属していない社員を取得する(LEFT JOIN + IS NULL パターン)
SELECT e.name
FROM employees AS e
LEFT JOIN departments AS d ON e.department_id = d.id
WHERE d.id IS NULL;

よくあるミス

ON 句に絞り込み条件を書くと LEFT JOIN の結果が変わります。全社員が返るが、他部署の department_name はNULLになるだけで行は消えません。

SELECT e.name, d.department_name
FROM employees AS e
LEFT JOIN departments AS d
    ON e.department_id = d.id
    AND d.department_name = '未来ガジェット研究所';

ON 句に絞り込み条件を書いた場合: 全社員が返るが、他部署はNULLになります。

+------------+----------------------+
| name       | department_name      |
+------------+----------------------+
| 岡部倫太郎 | 未来ガジェット研究所 |
| 牧瀬紅莉栖 | NULL                 |
| 椎名まゆり | 未来ガジェット研究所 |
| 橋田至     | 未来ガジェット研究所 |
+------------+----------------------+
4 rows in set
SELECT e.name, d.department_name
FROM employees AS e
LEFT JOIN departments AS d ON e.department_id = d.id
WHERE d.department_name = '未来ガジェット研究所';

WHERE 句に条件を書いた場合: INNER JOIN と同等になり行が絞り込まれます。

+------------+----------------------+
| name       | department_name      |
+------------+----------------------+
| 岡部倫太郎 | 未来ガジェット研究所 |
| 椎名まゆり | 未来ガジェット研究所 |
| 橋田至     | 未来ガジェット研究所 |
+------------+----------------------+
3 rows in set

データベース別の書き方

『INNER JOIN ... ON』の構文は主要なデータベースで共通して使用できます。

-- MySQL・PostgreSQL・SQLite 共通
SELECT e.name, d.department_name, e.salary
FROM employees AS e
INNER JOIN departments AS d ON e.department_id = d.id;
+------------+------------------------------+--------+
| name       | department_name              | salary |
+------------+------------------------------+--------+
| 岡部倫太郎 | 未来ガジェット研究所         | 300000 |
| 牧瀬紅莉栖 | ヴィクトル・コンドリア大学   | 380000 |
| 椎名まゆり | 未来ガジェット研究所         | 280000 |
| 橋田至     | 未来ガジェット研究所         | 320000 |
+------------+------------------------------+--------+
4 rows in set

Oracle では従来『FROM テーブル1, テーブル2 WHERE 条件』の書き方が多く使われていましたが、Oracle 9i 以降は『INNER JOIN ... ON』が使用できます。

概要

『INNER JOIN』は関係データベースの核心的な機能で、正規化されたテーブルのデータを組み合わせて取得するために使用します。『ON』句に結合条件を記述し、両テーブルで条件を満たす行だけを返します。

『FROM テーブル1, テーブル2 WHERE テーブル1.id = テーブル2.id』という書き方は『INNER JOIN ... ON』と同等ですが、明示的に『JOIN』を書く方が読みやすいという意見もあります。

片方のテーブルに一致する行がない場合でも結果を含めたい場合は『LEFT JOIN / RIGHT JOIN』を使用してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。