5.自己結合-SQL経験者のためのR入門

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ではなく、ManagerIDEmployeeID で関連付ける場合)。
  • 行の比較: 同じテーブル内の異なるレコード間で、条件に基づいて比較を行う場合(例: 同じ部署にいる給与が自分より高い従業員を抽出する)。
  • 連続データの確認: 順序を持つデータセットで、現在のレコードと前後のレコードを比較する場合。

3. 具体的な例(階層構造)

従業員テーブル(Employees)があり、各従業員が上司(マネージャー)を持つ構造を考えます。

  • EmployeeID: 従業員ID
  • Name: 従業員名
  • 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の自己結合と同じ結果を得ることができます。