1. 導入: 外部結合がなぜ重要か
データベースの実務において、単一のテーブルだけで業務が完結することは稀です。多くの場合、複数のテーブルを関連付けてデータを取得しますが、ここで直面するのが「結合条件に一致しないデータ」をどう扱うかという問題です。内部結合(INNER JOIN)では、条件に合致しない行は問答無用で切り捨てられます。しかし、実務では「部署に所属していない社員」や「まだ注文のない顧客」など、「紐づくデータがなくても元のテーブルの行をすべて出力したい」という要件が頻繁に発生します。これを解決するのが外部結合(LEFT OUTER JOIN)です。
2. 基礎知識: 外部結合の仕組み
外部結合とは、結合対象となる2つのテーブルのうち、基準となるテーブル(通常は左側)の全データを保持したまま、もう一方のテーブルから一致するデータを「あれば結合、なければNULL」として補完する手法です。
SQLiteにおいては、LEFT OUTER JOIN のみをサポートしています。ここで注意が必要なのは、SQLiteでは「右外部結合(RIGHT OUTER JOIN)」や「完全外部結合(FULL OUTER JOIN)」がサポートされていない点です。もし右側のテーブルを基準にしたい場合は、テーブルの記述順を入れ替えてLEFT OUTER JOINを使用することで代替します。
3. 実装/解決策: 基本構文と現場での考え方
実務では「マスタテーブルにデータが存在しない場合に、どう表示するか」という制御が重要になります。結合条件(ON句)に一致しない行の右側カラムはすべて「NULL」になるため、アプリケーション側や表示側でこのNULLをどう扱うか(例:’未所属’と表示するなど)を設計段階で考慮する必要があります。
4. サンプルプログラム
以下は、社員テーブル(staff)と部署テーブル(dept)を用いた実用的なSQL例です。部署に所属していない社員(deptid=4)がどのように抽出されるかを確認してください。
— 1. テーブルの作成とデータ投入
CREATE TABLE staff(id INTEGER, name TEXT, deptid INTEGER);
INSERT INTO staff VALUES(1, ‘Suzuki’, 1);
INSERT INTO staff VALUES(2, ‘Endou’, 3);
INSERT INTO staff VALUES(5, ‘Takahashi’, 4); — 部署ID 4 は dept テーブルに存在しない
CREATE TABLE dept(id INTEGER, name TEXT);
INSERT INTO dept VALUES(1, ‘Sales’);
INSERT INTO dept VALUES(2, ‘Manage’);
INSERT INTO dept VALUES(3, ‘Dev’);
— 2. LEFT OUTER JOIN を使用した取得
— staff を起点にすることで、部署に所属していない ‘Takahashi’ も出力されます
SELECT
staff.name AS 社員名,
COALESCE(dept.name, ‘未所属’) AS 部署名 — NULLの場合に’未所属’と表示する実務テクニック
FROM staff
LEFT OUTER JOIN dept ON staff.deptid = dept.id;
5. 応用・注意点
現場でよくあるミスとして、WHERE句での絞り込みがあります。LEFT OUTER JOINの結果に対して「WHERE dept.id = 1」のように条件を指定すると、結果的に内部結合と同じ挙動になり、せっかく抽出した「NULL行(未所属者)」が消えてしまいます。
回避策:
結合したデータでフィルタリングしたい場合は、WHERE句ではなくON句に条件を記述してください。そうすることで、結合の段階でフィルタリングが適用され、意図通りの外部結合結果が得られます。また、前述のサンプルコードで使用した「COALESCE」関数は、NULL値を安全なデフォルト値に変換できるため、可読性向上とバグ回避のために積極的に活用しましょう。

コメント