応用情報技術者 2015年 秋期 午前2 問29
問題文
“倉庫別商品在庫集計” 表から在庫数の合計を求めたい。倉庫番号 'C003' の倉庫で在庫数が 100 以上の商品に対して、全ての倉庫における在庫数の合計を求める SQL文の aに入る適切な字句はどれか。ここで、該当する商品は複数存在するとともに在庫数が 100 未満の商品も存在するものとする。また、実線の下線は主キーを表す。
倉庫別商品在庫集計 (倉庫番号、商品コード、在庫数)
〔SQL文〕
SELECT 商品コード、SUM(在庫数) AS 在庫合計 FROM 倉庫別商品在庫集計
WHERE [ a ]
GROUP BY 商品コード
選択肢
ア:
商品コード = (SELECT 商品コード FROM 倉庫別商品在庫集計
WHERE 倉庫番号= 'C003' AND 在庫数 >= 100 )
イ:
商品コード = ALL(SELECT 商品コード FROM 倉庫別商品在庫集計
WHERE 倉庫番号 = 'C003' AND 在庫数 >= 100)
ウ:
商品コード IN (SELECT 商品コード FROM 倉庫別商品在庫集計
WHERE 倉庫番号 = 'C003' AND 在庫数 >= 100 )
(正解)エ:
EXISTS (SELECT * FROM 倉庫別商品在庫集計
WHERE 倉庫番号= 'C003' AND 在庫数 >= 100)
🔒 解説は解答すると表示されます
INによる商品絞り込み【午前2解説】
正解の理由
求める条件は「倉庫番号 'C003' において在庫数が 100 以上である商品(商品コード)に該当する商品だけを残し、全倉庫分の在庫を商品ごとに合計する」ことです。サブクエリで該当する商品コードを複数返すことが想定されるため、外側の WHERE 句で「商品コード が サブクエリの集合に含まれる」ことを表現する ウ の IN が適切です。IN はサブクエリが複数行を返しても各行と照合でき、意図どおり該当商品だけを抽出してから GROUP BY により在庫合計を求められます。
解法ステップ
- 求めたい対象を明確にする:C003 で在庫数 >= 100 の「商品コード」を取り出す。
- その商品コード群に該当する外側テーブルの行だけを残すフィルタを作る。
- フィルタ後に商品コードでグループ化して SUM(在庫数) を計算する。
- サブクエリが複数行を返すことを想定して、外側条件は集合演算(IN 等)で記述する。
実際の WHERE 部分は本問では次のようになります(省略形):
商品コード IN (SELECT 商品コード FROM 倉庫別商品在庫集計
WHERE 倉庫番号 = 'C003' AND 在庫数 >= 100)
選択肢別の誤答解説
- ア: 商品コード = (SELECT 商品コード ...)
- "=" によりスカラー比較を期待するため、サブクエリが複数行を返すと「サブクエリが複数行を返しました」のようなエラーになります。本問では該当商品が複数あると明記されているため不適切です。
- イ: 商品コード = ALL(SELECT 商品コード ...)
- ALL は「左辺がサブクエリのすべての値と等しい」ことを要求します。複数の異なる商品コードが返る場合、左辺がすべてと等しくなることは通常ありえず、期待する絞りになりません(サブクエリが単一値のときのみ成立し得る)。
- ウ: 商品コード IN (SELECT 商品コード ...)
- サブクエリが返す複数の該当商品コードの集合に対して、外側の各行の商品コードが含まれるかを判定するため、意図どおり絞り込めます。よって正解です。
- エ: EXISTS (SELECT * FROM ...)
- この形は「サブクエリに1行でも該当行が存在するか」を判定する無相関 EXISTS です。本問のサブクエリ条件(倉庫番号='C003' AND 在庫数>=100)に該当する行が存在するならば WHERE EXISTS(...) は常に真となり、商品コードによる個別の絞り込みになりません。したがって不適切です。
- 補足:EXISTS は相関サブクエリとして用い、外側の行の値と内部を比較する形(例: WHERE EXISTS(SELECT 1 FROM ... WHERE outer.商品コード = inner.商品コード AND 倉庫番号='C003' AND 在庫数>=100))にすれば、外側の各行ごとに「その商品がC003で在庫>=100か」を確認でき、今回と同等の絞り込みが可能です。エは相関がなく無条件の存在確認になっている点が問題です。
よくある誤解
- 「EXISTS は常に行ごとにチェックする」と誤解することがある。実際には EXISTS が行ごとにチェックされるかはサブクエリが外側の列を参照している(相関している)かに依存する。無相関なら結果は全行同一(真または偽)になる。
- ALL の意味を取り違える:ALL は「いずれかに一致する」の ANY/IN とは逆で、「すべてと等しい」ことを要求するため、集合比較には通常向かない。
- "=" と IN を混同する:サブクエリが複数行を返す場面では "=" は使えない(エラー)ため、集合比較が必要。
補足コラム
相関EXISTS を使う書き方(本問と同等の効果を持つ別解例):
SELECT 商品コード, SUM(在庫数) AS 在庫合計
FROM 倉庫別商品在庫集計 t_outer
WHERE EXISTS (
SELECT 1 FROM 倉庫別商品在庫集計 t_inner
WHERE t_inner.商品コード = t_outer.商品コード
AND t_inner.倉庫番号 = 'C003'
AND t_inner.在庫数 >= 100
)
GROUP BY 商品コード;
パフォーマンス面では、DBMS の最適化によって IN、EXISTS、JOIN の実行計画が変わるため一概にどれが速いとは言えません。データ量やインデックス、NULL の有無によって最適な書き方は変わるため、実運用では実行計画を確認してください。
FAQ
Q: サブクエリに重複する商品コードがあっても問題ないか?
A: IN は集合として照合するため、重複があっても動作に影響はありません。パフォーマンス面で気になる場合は DISTINCT を使うこともありますが、不要な処理は避けた方がよいこともあります。
A: IN は集合として照合するため、重複があっても動作に影響はありません。パフォーマンス面で気になる場合は DISTINCT を使うこともありますが、不要な処理は避けた方がよいこともあります。
Q: NULL を含む商品コードはどう扱われる?
A: IN の挙動は NULL の扱いに注意が必要です。外側の値が NULL の場合、IN の比較は通常真にはならず除外されます。スキーマ上で商品コードが NOT NULL なら問題ありません。
A: IN の挙動は NULL の扱いに注意が必要です。外側の値が NULL の場合、IN の比較は通常真にはならず除外されます。スキーマ上で商品コードが NOT NULL なら問題ありません。
Q: = ALL と = ANY(= ANY は = SOME と同義)の違いは?
A: = ALL は「左辺がサブクエリのすべての値と等しい」ことを要求します。= ANY(= SOME)は「左辺がサブクエリのいずれかの値と等しい」すなわち IN と同等です。
A: = ALL は「左辺がサブクエリのすべての値と等しい」ことを要求します。= ANY(= SOME)は「左辺がサブクエリのいずれかの値と等しい」すなわち IN と同等です。
関連キーワード: SQL、サブクエリ、IN句、EXISTS、相関サブクエリ、GROUP BY、集合演算、ALL句、パフォーマンス

\ せっかくなら /
応用情報技術者を
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

