LWP | SQLのONとWHEREはなぜ違うのか
SQLのONとWHEREはなぜ違うのか
LEFT JOINにしたのに社員が消えた。残したい行から条件を考えよう。
ストーリー
コイ丸先輩は、社員を全員残すつもりでLEFT JOINを使いました。ところが部門名を「経理」に絞ると、一人しか残りません。アユさんと、社員の一行・部門の一行・部門IDの対応を確かめ、ONとWHEREが決める範囲を見直します。
社員4行・部門3行は架空の説明用データです。社員の部門ID30に対応する部門はなく、高橋さんの部門IDはNULLです。部門IDは部門表で一意という前提です。
1 社員と部門、何が対応する?

図1|社員4行と部門3行を部門IDで対応させる。30・NULL・40には対応する相手がない。
2 INNER JOINとLEFT JOIN

図2|INNER JOINは対応する田中・鈴木の2行、LEFT JOINは社員側の佐藤・高橋も残す4行となる。
3 ONに「経理」を置くと

図3|LEFT JOINのONへ経理条件を加えると、鈴木だけが部門行と対応し、社員4行は残る。
4 WHEREに「経理」を置くと

図4|LEFT JOIN後のWHEREはTRUEになる行だけを残す。経理は鈴木1行となり、NULL比較はUNKNOWNになる。
5 INNER JOINでは同じ結果

図5|INNER JOINでは、同じ経理条件をONとWHEREのどちらに置いても、対応する鈴木1行が残る。
6 4つの結果を並べてみる

図6|INNERはON・WHEREとも鈴木1行。LEFTはONで社員4行、WHEREで鈴木1行となる。
7 残したい行から、条件を置く

図7|結合する組合せをON、最終結果に残す行をWHEREで考える。図の順番は論理的な説明であり、物理実行順ではない。
まとめ
ONは結合する組合せの条件、WHEREは結合結果に残す行の条件です。LEFT JOINで経理条件をONへ置くと社員4行が残り、WHEREへ置くと鈴木さん1行だけが残ります。NULLと「経理」の比較はUNKNOWNになり、WHEREはTRUEの行だけを残します。結合・NULL補完・絞込みの順番は意味を説明するための論理的な整理で、DBの物理的な実行順を強制するものではありません。
今回の仕掛け
同じ社員・部門データを全図で使い、結合の種類と条件の置き場所だけを変えました。結果の違いはPostgreSQL公式の表式・結合の説明にも照合しています。
INNER JOINで結果が同じになる例と、LEFT JOINで結果が変わる例を並べ、要件の「全社員を残す」「経理の社員だけを残す」へ戻りました。条件を置く場所による速度差は測定していません。
今回のソースコードのサンプル
サンプルコード 同じLEFT JOINでONとWHEREを比べる(SQLite)
01 |
|
|---|---|
02 |
|
03 |
|
04 |
|
05 |
|
06 |
|
07 |
|
08 |
|
09 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
関数の説明
関数を定義する例ではなく、共通の入力をWITHで用意し、二つのLEFT JOINの結果をUNION ALLで並べるSQLです。
コードの説明
patternがONの行は経理条件を結合条件に含め、WHEREの行は部門IDで結合した後の結果を経理条件で絞ります。emp_id・emp_name・dept_idは図の社員ID・氏名・部門IDに対応します。入力が小さいため、比較の結果を手でも確認できます。
入力・概要
社員は田中10・鈴木20・佐藤30・高橋NULLの4行、部門は営業10・経理20・総務40の3行です。WITHのVALUESを使えるSQLite向けの単独クエリです。
結果
ON側は田中NULL・鈴木経理・佐藤NULL・高橋NULLの4行、WHERE側は鈴木経理の1行、合計5行になります。NULLの表示方法は使用するクライアントで変わります。
読むポイント
条件を移す前に、経理以外の社員を残す必要があるかを確かめます。NULLは空文字や0と置き換えません。実行確認は隔離したSQLite上で行い、既存の業務DBは使用していません。
出典メモ
元ネタ:[採用原稿 260917_SQL_ON_WHERE_JOIN_トラブルから理解する.md](<C:/LWP/記事制作/01_記事ネタ/archive/260917_SQL_ON_WHERE_JOIN_トラブルから理解する.md>)。2026年10月4日に原稿全文を確認し、説明単位に沿って再構成しました。元ネタの原文は保全しています。人物・業務データは創作・説明用です。
図の文字・番号・参照・金額を目視確認し、SQLの例は隔離したSQLiteで実行しました。簿記例はこのモデルの計算と借貸一致を確認しています。実業務の帳簿や業務DBを検証した記事ではありません。
Copyright © 2026 LWP 山中 一弘
本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。
