5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

暗黙的なJOINはやめよう

Posted at

あまり生のsqlを書かなくなり、ちょっとしたことでAIに聞いてみたら、
さらっと暗黙的なJoinが修正されてちょっとした気づきを得たので、
暗黙的なJOINの問題と改善したものにメモ的に残します。


暗黙的なJOINとは

暗黙的なJOINは、FROM句で複数のテーブルを,で区切り、WHERE句で結合条件を書く古い書き方です。

例:暗黙的なJOIN(古い書き方)

SELECT e.name, d.department_name
FROM employees e, departments d
WHERE e.department_id = d.department_id
  AND e.salary > 500000;

暗黙的なJOINの問題点

1. 可読性が低い

  • 結合条件とフィルタ条件が混在してWHERE句が複雑になる
  • どのテーブル同士が結合されているかが分かりにくい

2. メンテナンスが困難

  • 複数のテーブルが関わると、どれが結合条件でどれがフィルタ条件か判別しづらい
  • 結合条件を忘れやすく、意図しないクロス結合(デカルト積)が発生する危険性

3. 外部結合が書けない

  • LEFT JOIN、RIGHT JOIN、FULL OUTER JOINが表現できない

4. エラーが発見しにくい

-- 結合条件を忘れた場合(危険!)
SELECT e.name, d.department_name
FROM employees e, departments d
WHERE e.salary > 500000;  -- 結合条件なし → クロス結合

モダンなSQL(推奨される書き方)

1. 明示的なJOIN

-- 上記の例をモダンに書き直し
SELECT e.name, d.department_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.department_id
WHERE e.salary > 500000;

2. 外部結合も明確に表現可能

-- 部署に所属していない従業員も含める
SELECT e.name, COALESCE(d.department_name, 'No Department')
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
WHERE e.salary > 500000;

3. 複数テーブルの結合も読みやすい

SELECT e.name, d.department_name, p.project_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.department_id
INNER JOIN employee_projects ep ON e.employee_id = ep.employee_id
INNER JOIN projects p ON ep.project_id = p.project_id
WHERE e.salary > 500000
  AND p.status = 'ACTIVE';

モダンなSQLのベストプラクティス

1. JOINの種類を明示

-- 良い例
INNER JOIN departments d ON e.department_id = d.department_id
LEFT JOIN addresses a ON e.employee_id = a.employee_id

-- 避けるべき(JOINだけだとINNER JOINになるが、明示的に書く方が良い)
JOIN departments d ON e.department_id = d.department_id

2. テーブルエイリアスは意味のある名前を使用

-- 良い例
FROM employees emp
INNER JOIN departments dept ON emp.department_id = dept.department_id

-- 避けるべき(意味不明)
FROM employees a
INNER JOIN departments b ON a.department_id = b.department_id

3. 複雑なクエリは適切にインデントとフォーマット

SELECT 
    emp.employee_id,
    emp.name,
    dept.department_name,
    proj.project_name,
    CASE 
        WHEN emp.salary > 800000 THEN 'Senior'
        WHEN emp.salary > 500000 THEN 'Mid'
        ELSE 'Junior'
    END AS level
FROM employees emp
    INNER JOIN departments dept 
        ON emp.department_id = dept.department_id
    LEFT JOIN employee_projects ep 
        ON emp.employee_id = ep.employee_id
    LEFT JOIN projects proj 
        ON ep.project_id = proj.project_id
WHERE emp.status = 'ACTIVE'
    AND dept.budget > 1000000
ORDER BY emp.name;

4. WITH句(CTE)を活用

複雑なクエリは共通テーブル式(CTE)で分割する:

WITH active_employees AS (
    SELECT employee_id, name, department_id, salary
    FROM employees 
    WHERE status = 'ACTIVE'
),
high_budget_departments AS (
    SELECT department_id, department_name
    FROM departments
    WHERE budget > 1000000
)
SELECT 
    ae.name,
    hbd.department_name,
    ae.salary
FROM active_employees ae
INNER JOIN high_budget_departments hbd 
    ON ae.department_id = hbd.department_id
ORDER BY ae.salary DESC;

実際の移行例

Before(暗黙的JOIN)

SELECT k.sya_id, k.kyoyob08, s.ship_kb
FROM kyomst k, syainjh s, paykojin p
WHERE k.sya_id = s.sya_id
  AND k.sya_id = p.sya_id
  AND k.sdate <= TO_DATE('2025-08-29', 'YYYY-MM-DD')
  AND k.edate >= TO_DATE('2025-08-29', 'YYYY-MM-DD')
  AND p.s_key = 'SAMPLE';

After(モダンなSQL)

SELECT 
    k.sya_id,
    k.kyoyob08,
    s.ship_kb
FROM kyomst k
    INNER JOIN syainjh s ON k.sya_id = s.sya_id
    INNER JOIN paykojin p ON k.sya_id = p.sya_id
WHERE k.sdate <= TO_DATE('2025-08-29', 'YYYY-MM-DD')
    AND k.edate >= TO_DATE('2025-08-29', 'YYYY-MM-DD')
    AND p.s_key = 'SAMPLE'
ORDER BY k.sya_id;

まとめ

モダンなSQLの利点:

  • 結合条件とフィルタ条件が明確に分離
  • 外部結合も自然に表現可能
  • 可読性・メンテナンス性の向上
  • 意図しないクロス結合を防げる
  • チームでのコードレビューが容易

移行のポイント:

  1. FROM句の,INNER JOIN ... ONに変更
  2. WHERE句の結合条件をON句に移動
  3. 外部結合が必要な箇所はLEFT/RIGHT JOINを使用
  4. 適切なフォーマットとエイリアス名を使用
5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?