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
サンプルコード
社員テーブルと部署テーブルを結合して、部署名とともに社員一覧を取得します。
社員テーブルと部署テーブルを結合して、部署名とともに社員一覧を取得します。
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』を使用してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。