SQLの自己結合(Self Join)について解説します。
🔁 自己結合(Self Join)とは
自己結合とは、同じテーブルを、あたかも異なる二つのテーブルであるかのように扱って結合する操作です。
基本的な JOIN 構文自体は通常のテーブル結合(例: INNER JOIN)と全く同じですが、結合する両側のテーブルとして同じテーブルを指定し、それぞれに異なるエイリアス(別名)を付けることが必須となります。
1. 構文と必須要素
自己結合の構文は次のようになります。
SQL
SELECT
A.column_name,
B.column_name
FROM
TableName AS A -- 必須: 1つ目のインスタンスにエイリアス 'A' を付ける
INNER JOIN
TableName AS B -- 必須: 2つ目のインスタンスにエイリアス 'B' を付ける
ON
A.JoinKey = B.JoinKey -- AとBの関連するキーをON句で指定
WHERE
A.ID <> B.ID; -- 多くのケースで、同じレコード同士の結合を除外する
2. 自己結合の利用目的
自己結合は、テーブル内の行同士を比較・関連付けたい場合に利用されます。主に以下のようなケースで使われます。
- 階層データの処理: 組織図やカテゴリ構造など、階層的な関係を持つデータ(例: 従業員テーブルの上司と部下の関係を、部署IDや役職IDではなく、
ManagerIDとEmployeeIDで関連付ける場合)。 - 行の比較: 同じテーブル内の異なるレコード間で、条件に基づいて比較を行う場合(例: 同じ部署にいる給与が自分より高い従業員を抽出する)。
- 連続データの確認: 順序を持つデータセットで、現在のレコードと前後のレコードを比較する場合。
3. 具体的な例(階層構造)
従業員テーブル(Employees)があり、各従業員が上司(マネージャー)を持つ構造を考えます。
EmployeeID: 従業員IDName: 従業員名ManagerID: この従業員の上司のEmployeeID
SQLクエリ(上司の名前を取得)
SQL
SELECT
-- 部下の情報
E.Name AS EmployeeName,
-- 上司の情報
M.Name AS ManagerName
FROM
Employees AS E -- E: Employee(部下)のインスタンス
INNER JOIN
Employees AS M -- M: Manager(上司)のインスタンス
ON
E.ManagerID = M.EmployeeID; -- 部下のManagerIDと、上司のEmployeeIDが一致
この操作により、Employees テーブルを2つの役割(部下E、上司M)として利用し、各従業員の上司名を横に並べて表示できます。
💻 R言語 (dplyr) での対応
R言語の dplyr パッケージでは、自己結合は通常の結合関数 (inner_join, left_join など) を使い、両方の引数に同じデータフレームを渡すことで実現されます。
Rコード例(自己結合)
上記の「上司の名前を取得する」例をRで再現します。
R
library(dplyr)
# データフレームの準備 (ManagerID列を追加)
Employees <- data.frame(
EmployeeID = 1:6,
Name = c("Alice", "Bob", "Charlie", "David", "Eve", "Frank"),
ManagerID = c(3, 3, NA, 5, 3, 5) # Charlieは上司なし
)
# 自己結合の実行
Employees %>%
# 左結合を使用し、すべての従業員(部下)を保持する (Charlieも含む)
left_join(
Employees, # 右側のテーブルも同じEmployeesを指定
by = c("ManagerID" = "EmployeeID"), # 結合キーを指定: 左のManagerID = 右のEmployeeID
suffix = c("_Employee", "_Manager") # 同名の列 (Name) にエイリアスを付与
) %>%
select(
EmployeeName = Name_Employee, # 部下の名前
ManagerName = Name_Manager # 上司の名前
)
このRコードにより、SQLの自己結合と同じ結果を得ることができます。