データベーススペシャリスト 2021年 午前2 問08
問題文
“社員取得資格”表に対しSQL文を実行して結果を得た。SQL文の(a)に入れる字句はどれか。

選択肢
ア:
ON C1.社員コード = C2.社員コード
AND C1.資格 = 'FE' AND C2.資格 = 'AP'
WHERE C1.資格 = 'FE'
(正解)イ:
ON C1.社員コード = C2.社員コード
AND C1.資格 = 'FE' AND C2.資格 = 'AP'
WHERE C1.資格 IS NOT NULL
ウ:
ON C1.社員コード = C2.社員コード
AND C1.資格 = 'FE' AND C2.資格 = 'AP'
WHERE C2.資格 = 'AP'
エ:
ON C1.社員コード = C2.社員コード
WHERE C1.資格 = 'FE' AND C2.資格 = 'AP'
🔒 解説は解答すると表示されます
自己結合による列展開【午前2解説】
正解の理由
選択肢アが正解です。目的は「資格が 'FE' の行を基点(左側)にして、同じ社員コードのうち資格が 'AP' の行を右側に結合し、APがなければNULLを受け取る」ことです。これを実現するには、右側(C2)の絞り込み条件 C2.資格 = 'AP' をON句に入れておく必要があります。ON句に入れることで、左外部結合(LEFT OUTER JOIN)は「C1 の行は必ず残し、C2 が条件に合致しない場合は NULL を埋める」動作をします。さらに C1 側を 'FE' に絞るために WHERE C1.資格 = 'FE' を使うのも正当で、結果は期待どおりになります。
(選択肢アの記述は C1.資格 = 'FE' がON句とWHERE句の両方にあるため冗長ですが、動作としては期待結果と一致します。)
解法ステップ
- 出力されている結果を観察して、基点テーブルがどの行かを判断する(資格1 が常に 'FE' の行が基点である)。
- 「右側に AP を配置し、なければ NULL を表示する」という要件は LEFT JOIN を使うことを意味する。
- 右側(結合先)に対する絞り込み(C2.資格 = 'AP')は ON に書く。WHERE に書くと結合後の行(NULL を含む行)を排除してしまい、LEFT JOIN の意味が失われる。
- 左側の絞り込み(C1.資格 = 'FE')は WHERE に書くのが自然(ON に書いても結果は同じだが冗長になり得る)。
例:期待される簡潔な実装
SELECT C1.社員コード, C1.資格 AS 資格1, C2.資格 AS 資格2
FROM 社員取得資格 C1
LEFT JOIN 社員取得資格 C2
ON C1.社員コード = C2.社員コード
AND C2.資格 = 'AP'
WHERE C1.資格 = 'FE';
選択肢別の誤答解説
-
ア(正解)
- ON に C2.資格 = 'AP' を置き、WHERE で C1.資格 = 'FE' を指定しているため、左側の 'FE' 行は残り、右側に該当する 'AP' があれば表示、なければ NULL になる。期待結果と一致する。C1.資格 = 'FE' がONとWHEREの両方にあるのは冗長だが動作上の問題はない。
-
イ
- ON に C2.資格 = 'AP' があり、WHERE に C1.資格 IS NOT NULL がある構成です。ここで注意すべきは、WHERE C1.資格 IS NOT NULL は「NULL の行だけを除外する」条件であって「'FE' の行だけを残す」条件ではない点です。つまり C1 の全ての非NULL資格(FE以外の AP, DB, SM など)も基点として残ってしまい、期待される「資格1 が常に FE」という出力にはならず、不要な行が増えます。したがって誤りです。
-
ウ
- WHERE に C2.資格 = 'AP' を書いていますが、これは結合後に適用されるため、C2.資格 が NULL の行(右側マッチがない行)を排除します。結果的に LEFT JOIN が事実上 INNER JOIN のようになり、C2 に AP を持たない社員(例:S002, S003)の行が消えてしまいます。構文的に問題はありませんが、要件(AP がなければ NULL を残す)を満たしません。
-
エ
- ON に社員コードの一致のみを書き、WHERE に C1.資格 = 'FE' AND C2.資格 = 'AP' を書いています。C2.資格 = 'AP' が WHERE にあるため、結合後に右側が NULL の行は除外されます(これも LEFT JOIN を無効化)。従って AP を持たない FE の社員が結果から消え、期待結果と合致しません。
よくある誤解
- WHERE 句は結合の前に評価されると思い込む
- 実際には WHERE は結合結果に対するフィルタです。右側(結合先)に関する条件を WHERE に書くと NULL を含む行を排除し、LEFT JOIN の意味が失われます。
- IS NOT NULL で目的の値だけを指定できると考える誤り
- WHERE C1.資格 IS NOT NULL は NULL を除外するだけで、'FE' 以外の有効な値(AP, DB, SM 等)も通してしまいます。特定値で絞るには = 'FE' を使う必要があります。
補足コラム
- ON と WHERE の使い分け
- ON:結合ペアの条件を指定する(どの行を「マッチ」とみなすか)→ LEFT JOIN の場合、マッチしない右側は NULL になる。
- WHERE:結合後の行を最終的に残すか捨てるかを決定するフィルタ→ここで右側の列を条件に含めると、マッチしなかった行が捨てられ LEFT JOIN が実質的に INNER JOIN になることがある。
- 実務的ヒント
- 左側の絞り込み(基点の行)を WHERE に書き、右側の絞り込み(結合対象の種類)を ON に書くのが分かりやすくバグも起きにくいです。
- 同じ表を自己結合する場合、テーブルエイリアス(C1, C2)を明示し、どちらの列かを明確にすることが重要です。
FAQ
Q: ON に書く条件は複雑でも構わないですか?
A: はい、結合条件として必要な論理は ON に書けます。ただし、左外部結合で右側を絞る条件は必ず ON に入れないと NULL 行が排除される点に注意してください。
A: はい、結合条件として必要な論理は ON に書けます。ただし、左外部結合で右側を絞る条件は必ず ON に入れないと NULL 行が排除される点に注意してください。
Q: C1 側の絞り込みも ON に書いていいですか?
A: 書けますが冗長になることがあります。C1 に関するフィルタは WHERE に置くのが自然で、読みやすさと意図の明確化に役立ちます。
A: 書けますが冗長になることがあります。C1 に関するフィルタは WHERE に置くのが自然で、読みやすさと意図の明確化に役立ちます。
Q: LEFT JOIN と WHERE の順序は実行計画にどう影響しますか?
A: 実行計画は最終的な論理と等価になるよう最適化されますが、SQL の書き方で意図が変わること(LEFT JOIN を失わせる等)は論理的に重要です。可読性と正確さを優先してください。
A: 実行計画は最終的な論理と等価になるよう最適化されますが、SQL の書き方で意図が変わること(LEFT JOIN を失わせる等)は論理的に重要です。可読性と正確さを優先してください。
関連キーワード: SQL、LEFT JOIN、自己結合、ON句とWHERE句の違い、NULL扱い、結合条件、列別名、データ抽出

\ せっかくなら /
データベーススペシャリストを
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

