コマンド道場
ON 句と USING 句難易度 ★★★★

ON と WHERE のどちらに書くか

すべての部署について、2020 年 1 月 1 日以降に入社した社員の人数を求めてください。該当する社員が 1 人もいない部署も、人数 0 として結果に含めてください。列は「busho_name, ninzu」の順、人数の多い順、人数が同じ場合は部署名の昇順に並べてください。

この書き方が使えない製品があります そのまま使える: PostgreSQL / MySQL / MariaDB / IBM Db2

  • SQLite では使えませんDATE 'YYYY-MM-DD' の日付リテラル
  • SQL Server では使えませんDATE 'YYYY-MM-DD' の日付リテラル
  • Oracle Database では使えませんDATE 'YYYY-MM-DD' の日付リテラル

製品ごとの対応表(実測)を見る

  • ON に条件を足すと、LEFT JOIN で「条件に合う相手だけを結合する」ことができます。同じ条件を WHERE に書くと、相手がいない行ごと消えて内部結合と同じ結果になります。
  • 模範解答の DATE 'YYYY-MM-DD' という日付リテラルは、SQLite と SQL Server では使えません。'2025-01-01' と文字列で書くか、CAST('2025-01-01' AS DATE) と書きます(Oracle も DATE リテラルはありますが書式が異なります)。
● 起動中…

この問題で使えるテーブル(名前をタップすると入力できます)

7

NULL
🔑int不可
text不可
int
データを見る(先頭 5 行)
busho_idbusho_nameparent_busho_id
1経営NULL
2開発1
3営業1
4管理1
5基盤2

18

NULL
🔑int不可
text不可
int
int
numeric(10,0)不可
date不可
date
データを見る(先頭 5 行)
shain_idnamebusho_idjoushi_idsalaryhired_ontaishoku_on
1鈴木1NULL9800002014-04-01NULL
2佐藤217200002016-10-01NULL
3田中225200002019-04-01NULL
4中村225300002020-04-01NULL
5小林224450502024-04-01NULL

解説

結論

外部結合で「残したい側」を保ちたいなら、相手側への条件は ON に書きます

★なぜ WHERE では消えるのか: 外部結合は「まず結合し、相手がいなければ相手側の列を NULL で埋める」処理です。該当者が 0 人の部署(経営・法務)は s.hired_on が NULL になります。ここで WHERE s.hired_on >= DATE '2020-01-01' と書くと、NULL との比較結果は真でも偽でもなく不明なので、WHERE はこの行を通しません。結果として行ごと捨てられ、外部結合が実質的に内部結合と同じになります。

ON に書けば条件は「結合の段階」で適用され、相手が見つからなくても左側の行は残ります。

⚠️ 例外に注意

条件が IS NULL の場合は NULL に対してになるので行は消えません。つまり「WHERE に書くと必ず消える」わけではなく、NULL に対して真にならない条件(比較・等値・IS NOT NULL)のときに消えるのが正確な理解です。

よくある間違い

count(*) を使う。外部結合では相手がいない行も 1 行として存在するので、該当者 0 人の部署が 1 人になります。人数を数えるときは必ず相手側の列を渡してください。

ON 句と USING 句 の使い方をはじめから読む

根拠(一次情報)