戦国IT - 情報処理技術者試験の過去問対策サイト
ブログお知らせお問い合わせ料金プラン

データベーススペシャリスト 2024年 午前208


問題文

図のツリー構造に対するデータを格納した“隣接リスト”表から、リーフノードを取得するSQL文のaに入れる字句はどれか。ここで、図の丸はノードを表し、矢印は親ノードから子ノードへの関係を表す。
データベーススペシャリスト 2024年 午前2 問08の問題画像

選択肢

EXCEPT(正解)
INTERSECT
UNION
UNION ALL

🔒 解説は解答すると表示されます

リーフノード抽出【午前2解説】

正解の理由

ツリーのリーフは「子として存在するが親としては存在しない」ノードです。したがって、まず全ての子ノードの集合を取得し、そこから親ノードの集合を差し引く(集合差)必要があります。SQLの集合演算子で集合差を表すのが の EXCEPT であり、次のように「子ノード集合 EXCEPT 親ノード集合」とすることで、親として現れない子(=リーフ)だけが残ります。EXCEPT は集合演算なので重複を排除して返す点もリーフ抽出には適しています。
例(結果として得られるリーフ): D, E, G

解法ステップ

  1. 隣接リストの子ノード全体を取得する
    SELECT 子ノード FROM 隣接リスト
  2. 隣接リストの親ノード全体を取得する
    SELECT 親ノード FROM 隣接リスト
  3. 子ノード集合から親ノード集合を差し引く(子 − 親)
    この差を表すのが EXCEPT()なので、順序は必ず「子ノード側を先に、親ノード側を後に」書くこと。
SQL例:
SELECT 子ノード FROM 隣接リスト
EXCEPT
SELECT 親ノード FROM 隣接リスト;
備考: 実行結果の順序は保証されないため、特定の順序で結果を得たい場合は最後に ORDER BY を付けます。

選択肢別の誤答解説

  • EXCEPT
    正解。集合差(左側から右側を取り除く)を実現するので「子集合から親集合を引く」ことができる。
  • イ INTERSECT
    共通部分(子かつ親)を返す。内部ノード(親でもあり子でもあるノード)を返すためリーフ抽出には逆効果。
  • ウ UNION
    和集合(重複排除)を返す。子と親の全てをまとめてしまうため、リーフの抽出にはならない。
  • エ UNION ALL
    和集合のうち重複排除を行わない版。重複をそのまま残すため結果が冗長になる上、リーフ抽出にならない。

よくある誤解

  • EXCEPT の順序を逆に書いてしまう(親 EXCEPT 子)
    これをやると「親であって子でない」ノードが残り、リーフではなく根や中間の親のみが返る。正しくは「子の集合」から「親の集合」を引く。
  • NULL の扱いを混同する
    親ノード列に NULL(ルートの親)が存在しても、子ノード列の値と NULL は等しくないため差集合処理に誤りは生じない。ただし NULL の比較や集計を扱う場合は実際のDB挙動に注意する(DBによって NULL の扱い差はある)。
  • 結果の順序を期待してしまう
    EXCEPT は集合演算のため順序は保証されない。ソートが必要なら ORDER BY を付与する。

補足コラム

ポータビリティや別解法について:
  • Oracle では集合差に MINUS を使います(SELECT 子ノード FROM 隣接リスト MINUS SELECT 親ノード FROM 隣接リスト)。
  • MySQL 等で EXCEPT/MINUS 未対応の場合は NOT EXISTS や LEFT JOIN を使う方法が一般的で、いずれも意図は「その子ノードを親列に持つ行が存在しない」ことの確認です。
代替クエリ(NOT EXISTS、左外部結合のアンチ結合):
-- NOT EXISTS(多くのDBで推奨される方法)
SELECT c.子ノード
FROM 隣接リスト c
WHERE NOT EXISTS (
  SELECT 1 FROM 隣接リスト p WHERE p.親ノード = c.子ノード
);

-- LEFT JOIN を使う方法(結合結果が存在しない行を抽出)
SELECT c.子ノード
FROM 隣接リスト c
LEFT JOIN 隣接リスト p ON p.親ノード = c.子ノード
WHERE p.子ノード IS NULL;

FAQ

Q. EXCEPT と MINUS は同じですか?
A. 概念上は同じ(集合差)ですが、SQL標準では EXCEPT、Oracle は歴史的に MINUS を使います。実装や NULL の扱いに差がある場合もあるため使用するDBの仕様を確認してください。
Q. 重複する子ノードがある場合は?
A. EXCEPT は集合演算なので重複は排除されます。重複を残したい場合はデータの前処理や ROW_NUMBER() 等を工夫する必要があります。
Q. 実行順序(子側を先に書く)を忘れたらどうなる?
A. 順序を逆にすると意図と反対の集合(親から子を引いた集合)が得られ、リーフではないノード群が返ります。集合差は順序依存なので注意してください。

関連キーワード: 隣接リスト、EXCEPT、集合差、リーフノード、アンチ結合
← 前の問題へこの年度をクイズで解く次の問題へ →
戦国ITクイズ機能

\ せっかくなら /

データベーススペシャリスト
クイズ形式で学習しませんか?

クイズ画面へ遷移する

すぐに利用可能!

©︎2026 情報処理技術者試験対策アプリ

このサイトについてブログプライバシーポリシー利用規約特商法表記開発者について