システムアーキテクト 2009年 午前2 問23
問題文
“納品”表と“顧客”表を自然結合するSQL文はどれか。


選択肢
ア:SELECT *
FROM 納品, 顧客
WHERE 納品.顧客番号 = 顧客.顧客番号
イ:SELECT 顧客.顧客番号, 納品.商品番号, 納品.納品数量, 顧客.顧客名
FROM 納品, 顧客
WHERE 納品.顧客番号 <> 顧客.顧客番号
ウ:SELECT 納品.顧客番号, 納品.商品番号, 納品.納品数量
FROM 納品
WHERE 納品.顧客番号 IN (SELECT 顧客番号 FROM 顧客)
エ:SELECT 納品.顧客番号, 納品.商品番号, 納品.納品数量, 顧客.顧客名
FROM 納品, 顧客
WHERE 納品.顧客番号 = 顧客.顧客番号(正解)
🔒 解説は解答すると表示されます
自然結合【午前2解説】
正解の理由
自然結合(NATURAL JOIN)は、同名の全ての列で等値結合を行い、結合結果で同名列を一つだけ残すという振る舞いが特徴です。与えられた二表は「顧客番号」を共通列として持つため、自然結合の結果は「顧客番号、商品番号、納品数量、顧客名」の4列が得られます。
選択肢の中で、これと同じ列構成を明示的に指定し、かつ結合条件に等号(=)を用いているのは エ です。したがって エ が正解です。
選択肢の中で、これと同じ列構成を明示的に指定し、かつ結合条件に等号(=)を用いているのは エ です。したがって エ が正解です。
(補足)等値条件を WHERE で書く形式(いわゆる古い書き方)は結合の判定自体は INNER JOIN と同等ですが、SELECT 句で何を列挙するかによって出力列は変わります。特に SELECT * を使うと両表の共通列が重複して表示され、NATURAL JOIN の「共通列を一つにする」振る舞いとは異なります。
解法ステップ
- 表の共通列を確認する → 「顧客番号」が共通。
- 自然結合の出力列を想定する → 顧客番号(1つ)、商品番号、納品数量、顧客名。
- 各選択肢の SELECT 節と WHERE 節を比較する(出力列が適合するか、結合条件が等値か、否定や不適切な演算子がないか)。
- 出力列が自然結合と一致し、結合条件が等値である選択肢を選ぶ → エ。
選択肢別の誤答解説
-
ア
- WHERE 句で等値結合(納品.顧客番号 = 顧客.顧客番号)を行っているため結合の行は正しいが、SELECT * のため出力列は次のように「顧客番号が重複」してしまいます:
納品.顧客番号 | 商品番号 | 納品数量 | 顧客.顧客番号 | 顧客名 - NATURAL JOIN の期待結果は顧客番号が一つだけのため、出力列構成が異なり不適切。結合の判定は合っているが「列の扱い」が違う点を明確に区別する必要があります。
- WHERE 句で等値結合(納品.顧客番号 = 顧客.顧客番号)を行っているため結合の行は正しいが、SELECT * のため出力列は次のように「顧客番号が重複」してしまいます:
-
イ
- WHERE 句が
<>(不等)であり、等値で結合するどころか「顧客番号が異なる組合せ」だけを選んでしまいます。これは自然結合とは全く逆の条件です。
- WHERE 句が
-
ウ
- サブクエリによる IN 条件は、納品側の行を「顧客テーブルに対応する顧客番号が存在するものだけ」に絞る点では自然結合の行選択と一致します(いわゆるセミジョイン)。しかし SELECT 節が納品側の列のみを列挙しており、顧客名を出力していません。自然結合の出力には顧客名が含まれるため不一致です。
-
エ(正解の動作確認)
- SELECT 節で「納品.顧客番号、納品.商品番号、納品.納品数量、顧客.顧客名」を明示しており、WHERE によって等値結合(納品.顧客番号 = 顧客.顧客番号)を行っています。出力列は自然結合と一致するため正答です。
よくある誤解
- 「FROM と WHERE で等号を書けば NATURAL JOIN と同じ」と考える誤解
- 等号で結合する点は同じでも、SELECT * のように両表の同名列をそのまま全て取得すると列が重複します。NATURAL JOIN は同名列を一つにまとめる点が異なります。
- 「IN サブクエリは結合と同じ結果を返す」とする誤解
- IN は対象行をフィルタする(セミジョイン)ため、相手表の属性(ここでは顧客名)を取得しません。結合して属性を取得する必要がある場合は JOIN(あるいはサブクエリでさらに結合して取得)を使う必要があります。
- 「SELECT * は常に安全」と考える誤解
- 複数表を扱うと同名列の重複や列順・列名の曖昧さを招くため、明示的に列を列挙することが望ましいです。
補足コラム
-
NATURAL JOIN の書き方例(自動で同名列を結合し、重複列は一つにまとめる):
SELECT * FROM 納品 NATURAL JOIN 顧客;ただし、NATURAL JOIN は意図しない同名列が存在すると予期しない結合条件や列削除を招くため、実務では USING もしくは JOIN ... ON と明示的に書き、SELECT で必要な列を列挙する方が安全です。 -
USING を使うと、指定した共通列を一つにまとめて結合できます(列名は共通名で出力される):
SELECT 顧客番号, 商品番号, 納品数量, 顧客名 FROM 納品 JOIN 顧客 USING (顧客番号);これにより、エ と同等の出力を、より明示的に得られます。
FAQ
Q1. SELECT * と NATURAL JOIN を同時に使うとどうなる?
A1. NATURAL JOIN と組み合わせると、同名列は自動的に1列にまとめられますが、どの列が同名と判定されるかが自動で決まるため、意図しない列がまとめられるリスクがあります。可能なら明示的な列指定を推奨します。
A1. NATURAL JOIN と組み合わせると、同名列は自動的に1列にまとめられますが、どの列が同名と判定されるかが自動で決まるため、意図しない列がまとめられるリスクがあります。可能なら明示的な列指定を推奨します。
Q2. USING と NATURAL JOIN の違いは?
A2. USING は結合する列を明示的に指定します(例: USING (顧客番号))。NATURAL JOIN は同名列を自動判定して全て結合条件に使います。明示性の面で USING の方が安全です。
A2. USING は結合する列を明示的に指定します(例: USING (顧客番号))。NATURAL JOIN は同名列を自動判定して全て結合条件に使います。明示性の面で USING の方が安全です。
Q3. パフォーマンス差はあるか?
A3. 論理的には INNER JOIN と等価な処理であり、最適化や実行計画は DBMS に依存します。可読性と保守性の観点から、結合列を明示する書き方が一般に推奨されます。
A3. 論理的には INNER JOIN と等価な処理であり、最適化や実行計画は DBMS に依存します。可読性と保守性の観点から、結合列を明示する書き方が一般に推奨されます。
関連キーワード: SQL、JOIN、NATURAL JOIN、INNER JOIN、USING、等値結合、セミジョイン、SELECT *

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

