SELF JOIN
| 対応: | SQL-92(1992) |
|---|
同じテーブルを別名を付けて2つに見立て、自分自身と結合する手法です。階層データの親子関係の取得や、隣接する行の比較などに使われます。
構文
同じテーブルに異なるエイリアスを付けて結合します。
SELECT a.column, b.column FROM table AS a JOIN table AS b ON a.join_key = b.join_key;
構文一覧
| 構文 | 概要 |
|---|---|
| FROM table AS a JOIN table AS b | 同じテーブルに異なるエイリアスを付けて自己結合します。 |
| ON a.manager_id = b.employee_id | 親子関係や参照関係を結合条件に指定します。 |
サンプルコード
以下の『employees』テーブルを例に説明します。『manager_id』は同じテーブルの『employee_id』を参照しています。
社員テーブルで部下とその上司名を取得します。
sample_self_join.sql
SELECT
emp.name AS employee,
mgr.name AS manager
FROM employees AS emp
LEFT JOIN employees AS mgr ON emp.manager_id = mgr.employee_id;
+------------+------------+ | employee | manager | +------------+------------+ | 釘崎野薔薇 | NULL | | 五条悟 | 釘崎野薔薇 | | 虎杖悠仁 | 五条悟 | | 伏黒恵 | 五条悟 | +------------+------------+ 4 rows in set
同じ部署の社員同士のペアを列挙します(重複を避けるため employee_id で順序を制限)。
sample_self_join.sql
SELECT
a.name AS employee_a,
b.name AS employee_b,
a.department
FROM employees AS a
JOIN employees AS b
ON a.department = b.department
AND a.employee_id < b.employee_id
ORDER BY a.department, a.employee_id;
+------------+------------+------------+ | employee_a | employee_b | department | +------------+------------+------------+ | 釘崎野薔薇 | 五条悟 | 呪術高専 | | 釘崎野薔薇 | 虎杖悠仁 | 呪術高専 | | 釘崎野薔薇 | 伏黒恵 | 呪術高専 | | 五条悟 | 虎杖悠仁 | 呪術高専 | | 五条悟 | 伏黒恵 | 呪術高専 | | 虎杖悠仁 | 伏黒恵 | 呪術高専 | +------------+------------+------------+ 6 rows in set
データベース別の書き方
自己結合の構文は主要なデータベースで共通して使用できます。
-- MySQL・PostgreSQL・SQLite 共通 SELECT emp.name AS employee, mgr.name AS manager FROM employees AS emp LEFT JOIN employees AS mgr ON emp.manager_id = mgr.employee_id;
Oracle では『AS』キーワードをテーブルエイリアスに使えません。エイリアスを付ける際は『AS』を省略して記述します。
-- Oracle ではテーブルエイリアスに AS を使わない SELECT emp.name AS employee, mgr.name AS manager FROM employees emp LEFT JOIN employees mgr ON emp.manager_id = mgr.employee_id;
概要
『SELF JOIN』はSQLの特別な構文ではなく、通常の JOIN を同じテーブルに対して適用する手法です。テーブルエイリアスを必ず付けないと列の参照が曖昧になりエラーになるため、必ずエイリアスを指定してください。
主な用途は次の2つです。1つ目は「社員と上司」「カテゴリと親カテゴリ」のような階層データの親子関係の取得です。2つ目は同じテーブル内の行同士を比較する場面(同一部署の社員ペア・連続する日付の売上比較など)です。
親が存在しない行(トップレベルの社員など)も含めたい場合は『LEFT JOIN』を使うと NULL として取得できます。CROSS JOIN との違いは『CROSS JOIN』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。