データベースを扱う際、複数のテーブルから必要な情報を取得するためにJOINは欠かせない機能です。
しかし、単純な結合だけでは十分でない場合があります。
この記事では、SQLのJOINで複数の条件を指定する方法を、基本から応用まで初心者にもわかりやすく解説します。
JOINの基本概念を理解しよう

JOINとは何か
JOINとは、複数のテーブルを特定の条件に基づいて結合し、関連するデータを一つの結果として取得するSQL操作です。
JOINの基本的な役割:
- 複数テーブルのデータを組み合わせる
- リレーショナルデータベースの正規化されたデータを活用
- 効率的なデータ取得を実現
- 複雑なデータ分析を可能にする
JOINが必要な理由:
- データの重複を避けるため、情報が複数のテーブルに分かれている
- 効率的なストレージ使用のため
- データの整合性を保つため
- 保守性と可読性の向上
JOINの種類と特徴
INNER JOIN(内部結合):
- 両方のテーブルに一致するデータのみ返す
- 最も一般的に使用される結合方法
- 条件に合わないデータは結果に含まれない
LEFT JOIN(左外部結合):
- 左側のテーブルのすべてのデータを返す
- 右側のテーブルに一致するデータがない場合はNULLを返す
- データの欠損を許容する場合に使用
RIGHT JOIN(右外部結合):
- 右側のテーブルのすべてのデータを返す
- LEFT JOINの逆の動作
- あまり使用されない(LEFT JOINで代用可能)
FULL OUTER JOIN(完全外部結合):
- 両方のテーブルのすべてのデータを返す
- 一致しないデータはNULLで補完
- すべてのデータを保持したい場合に使用
基本的なJOIN構文

単一条件でのJOIN
最も基本的なJOINの書き方から始めましょう。
基本構文:
SELECT column_list
FROM table1
JOIN table2
ON table1.column = table2.column;
具体例:
SELECT e.name, d.department_name
FROM employees e
JOIN departments d
ON e.department_id = d.department_id;
構文の説明:
SELECT
:取得したいカラムを指定FROM
:メインとなるテーブルを指定JOIN
:結合するテーブルを指定ON
:結合条件を指定
テーブルエイリアスの活用
エイリアスとは:
- テーブル名に短い別名をつける機能
- 長いテーブル名を短縮して可読性を向上
- 同じテーブルを複数回結合する際に必須
エイリアスの例:
-- エイリアスなし(読みにくい)
SELECT employees.name, departments.department_name
FROM employees
JOIN departments
ON employees.department_id = departments.department_id;
-- エイリアスあり(読みやすい)
SELECT e.name, d.department_name
FROM employees e
JOIN departments d
ON e.department_id = d.department_id;
複数条件でのJOIN方法

AND条件による複数条件結合
複数の条件をすべて満たす場合のみ結合するには、AND演算子を使用します。
基本構文:
SELECT column_list
FROM table1
JOIN table2
ON table1.column1 = table2.column1
AND table1.column2 = table2.column2;
実用例:
SELECT e.employee_id, e.name, d.department_name
FROM employees e
JOIN departments d
ON e.department_id = d.department_id
AND e.location = d.location;
この例の説明:
- 部署IDが一致する
- かつ勤務地も一致する
- 両方の条件を満たすレコードのみ結合
より複雑な複数条件の例
3つ以上の条件を使った結合:
SELECT p.product_name, s.supplier_name, c.category_name
FROM products p
JOIN suppliers s
ON p.supplier_id = s.supplier_id
AND p.country = s.country
AND p.active_status = s.active_status;
異なる比較演算子を使った例:
SELECT o.order_id, c.customer_name
FROM orders o
JOIN customers c
ON o.customer_id = c.customer_id
AND o.order_date >= c.registration_date
AND o.status <> 'cancelled';
OR条件による複数条件結合
複数の条件のうち、いずれかを満たす場合に結合するには、OR演算子を使用します。
基本的なOR条件:
SELECT *
FROM table1 t1
JOIN table2 t2
ON t1.column1 = t2.column1
OR t1.column2 = t2.column2;
実用例:
SELECT e.name, d.department_name
FROM employees e
JOIN departments d
ON e.primary_dept_id = d.department_id
OR e.secondary_dept_id = d.department_id;
AND条件とOR条件の組み合わせ
複雑な論理条件の例:
SELECT p.product_name, s.supplier_name
FROM products p
JOIN suppliers s
ON (p.supplier_id = s.supplier_id OR p.alt_supplier_id = s.supplier_id)
AND p.status = 'active'
AND s.status = 'approved';
括弧を使った条件の明確化:
SELECT o.order_id, c.customer_name, p.product_name
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
JOIN products p
ON (o.product_id = p.product_id AND o.variant = p.variant)
OR (o.product_id = p.parent_product_id AND p.is_variant = true);
実践的な使用例
社員管理システムでの複数条件JOIN
テーブル構造の例:
-- 社員テーブル
CREATE TABLE employees (
employee_id INT PRIMARY KEY,
name VARCHAR(100),
department_id INT,
location VARCHAR(50),
hire_date DATE,
status VARCHAR(20)
);
-- 部署テーブル
CREATE TABLE departments (
department_id INT PRIMARY KEY,
department_name VARCHAR(100),
location VARCHAR(50),
manager_id INT,
budget DECIMAL(10,2)
);
複数条件でのJOIN例:
-- 同じ拠点の社員と部署を結合
SELECT
e.name AS employee_name,
d.department_name,
e.location
FROM employees e
JOIN departments d
ON e.department_id = d.department_id
AND e.location = d.location
AND e.status = 'active';
ECサイトでの商品・注文データの結合
複雑な条件での商品情報取得:
SELECT
o.order_id,
c.customer_name,
p.product_name,
p.price
FROM orders o
JOIN customers c
ON o.customer_id = c.customer_id
AND c.status = 'active'
JOIN products p
ON o.product_id = p.product_id
AND p.availability = 'in_stock'
AND o.order_date >= p.launch_date;
在庫管理システムでの複数条件結合
在庫と倉庫情報の結合:
SELECT
i.product_id,
p.product_name,
w.warehouse_name,
i.quantity
FROM inventory i
JOIN products p
ON i.product_id = p.product_id
AND p.status = 'active'
JOIN warehouses w
ON i.warehouse_id = w.warehouse_id
AND w.operational_status = 'open'
AND i.last_updated >= w.last_audit_date;
LEFT JOINでの複数条件

LEFT JOINと複数条件の組み合わせ
LEFT JOINでも複数条件を使用できます。これにより、より柔軟なデータ取得が可能になります。
基本的なLEFT JOIN with 複数条件:
SELECT
e.name,
d.department_name
FROM employees e
LEFT JOIN departments d
ON e.department_id = d.department_id
AND e.location = d.location;
NULL値の扱いに注意した例:
SELECT
c.customer_name,
o.order_id,
o.order_date
FROM customers c
LEFT JOIN orders o
ON c.customer_id = o.customer_id
AND o.status IN ('completed', 'shipped')
AND o.order_date >= '2024-01-01';
WHERE条件とON条件の違い
ON条件での絞り込み:
-- 結合時に条件を適用(推奨)
SELECT c.customer_name, o.order_id
FROM customers c
LEFT JOIN orders o
ON c.customer_id = o.customer_id
AND o.status = 'completed';
WHERE条件での絞り込み:
-- 結合後に条件を適用
SELECT c.customer_name, o.order_id
FROM customers c
LEFT JOIN orders o
ON c.customer_id = o.customer_id
WHERE o.status = 'completed' OR o.status IS NULL;
高度な複数条件JOIN技法
サブクエリを使った条件
EXISTS条件と組み合わせた例:
SELECT e.name, d.department_name
FROM employees e
JOIN departments d
ON e.department_id = d.department_id
AND EXISTS (
SELECT 1
FROM projects p
WHERE p.department_id = d.department_id
AND p.status = 'active'
);
CASE文を使った条件分岐
動的な結合条件:
SELECT
e.name,
d.department_name
FROM employees e
JOIN departments d
ON e.department_id = d.department_id
AND CASE
WHEN e.level = 'senior' THEN e.location = d.location
WHEN e.level = 'junior' THEN d.location = 'headquarters'
ELSE true
END;
日付範囲を使った複数条件
期間を考慮した結合:
SELECT
e.name,
p.project_name,
a.assignment_date
FROM employees e
JOIN project_assignments a
ON e.employee_id = a.employee_id
AND a.assignment_date BETWEEN e.hire_date AND COALESCE(e.termination_date, CURRENT_DATE)
JOIN projects p
ON a.project_id = p.project_id
AND p.start_date <= a.assignment_date
AND (p.end_date IS NULL OR p.end_date >= a.assignment_date);
パフォーマンス最適化のポイント
インデックスの活用
効果的なインデックス設計:
-- 複数条件に対応したインデックス
CREATE INDEX idx_emp_dept_location
ON employees (department_id, location, status);
-- JOINで使用するクエリ例
SELECT e.name, d.department_name
FROM employees e
JOIN departments d
ON e.department_id = d.department_id
AND e.location = d.location
AND e.status = 'active';
条件の順序最適化
選択性の高い条件を先に配置:
-- 最適化された条件順序
SELECT *
FROM large_table l
JOIN small_table s
ON l.unique_id = s.unique_id -- 高選択性
AND l.category = s.category -- 中選択性
AND l.status = 'active'; -- 低選択性
実行計画の確認
EXPLAIN文での性能確認:
EXPLAIN SELECT e.name, d.department_name
FROM employees e
JOIN departments d
ON e.department_id = d.department_id
AND e.location = d.location;
よくある間違いと対処法

間違いやすいケース
間違い1:結合条件の記述場所
-- 間違った例
SELECT *
FROM table1 t1
JOIN table2 t2
ON t1.id = t2.id
WHERE t1.status = t2.status; -- ONに書くべき条件
-- 正しい例
SELECT *
FROM table1 t1
JOIN table2 t2
ON t1.id = t2.id
AND t1.status = t2.status;
間違い2:括弧の使用忘れ
-- 間違った例(意図しない結果になる可能性)
SELECT *
FROM table1 t1
JOIN table2 t2
ON t1.id = t2.id
OR t1.alt_id = t2.id
AND t1.status = 'active';
-- 正しい例
SELECT *
FROM table1 t1
JOIN table2 t2
ON (t1.id = t2.id OR t1.alt_id = t2.id)
AND t1.status = 'active';
デバッグのコツ
段階的な確認方法:
-- 1. 基本的な結合を確認
SELECT COUNT(*) FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id;
-- 2. 条件を一つずつ追加
SELECT COUNT(*) FROM table1 t1 JOIN table2 t2
ON t1.id = t2.id AND t1.status = 'active';
-- 3. 最終的な複数条件
SELECT COUNT(*) FROM table1 t1 JOIN table2 t2
ON t1.id = t2.id AND t1.status = 'active' AND t1.location = t2.location;
まとめ
SQLのJOINで複数条件を使う方法について、重要なポイントをまとめます:
基本的な構文:
- AND条件:すべての条件を満たす場合の結合
- OR条件:いずれかの条件を満たす場合の結合
- 括弧使用:複雑な論理条件の明確化
- LEFT JOIN:外部結合でも複数条件が使用可能
実践的なポイント:
- 条件の記述場所(ON句 vs WHERE句)の理解
- テーブルエイリアスの活用
- パフォーマンスを考慮した条件順序
- インデックス設計との連携
よくある使用例:
- 社員と部署の詳細な結合
- 商品と在庫の複合条件結合
- 注文データの複雑な関連付け
- 期間を考慮したデータ結合
コメント