データベーススペシャリスト 2017年 午前2 問10
問題文
ある月の“月末商品在庫”と“当月商品出荷実績”表を使って、ビュー“商品別出荷実績”を定義した。このビューにSQL文を実行した結果の値はどれか。

選択肢
ア:400(正解)
イ:500
ウ:600
エ:700
🔒 解説は解答すると表示されます
ビューの集計とNULL処理【午前2解説】
正解の理由
ビュー側で各商品ごとの出荷合計(出荷実績数)を算出すると、出荷実績のない商品は集計結果がNULLになります。外側のSELECT句で使われている WHERE 出荷実績数 <= 300 は、ビューが返す集計結果に対する比較であり、NULL と比較した場合は真にならないため除外されます。したがって出荷実績数が数値として評価される商品だけが残り、それらの月末在庫数を合計します。該当するのは S001(出荷実績150、在庫100)と S003(出荷実績300、在庫300)で、月末在庫数の合計は となり、選択肢のうち ア に一致します。
解法ステップ
- ビュー定義の処理を想起する:LEFT OUTER JOIN と GROUP BY により、月末商品在庫の全行ごとに SUM(出荷数) を算出する。出荷が無い行の SUM は NULL。
- 各商品の出荷実績数を求める:
- S001: 50 + 100 = 150
- S002: 該当行なし → SUM = NULL
- S003: 150 + 150 = 300
- S004: 該当行なし → SUM = NULL
- S005: 100 + 250 = 350
- 外側クエリの WHERE 句(出荷実績数 <= 300)を適用する。NULL と比較した行(S002、S004)は除外される。残るのは S001 と S003。
- 残った行の月末在庫数を合計する:。
選択肢別の誤答解説
-
ア(400)
正しい。上記の通り、数値として比較可能な行は S001 と S003 のみで、在庫合計は 。 -
イ(500)
誤り。500 は例えば S003(300)と S005(200)を合算した値に相当しますが、本問では S005 の出荷実績は 350 であり 350 <= 300 は偽なので S005 は除外されます。S005 を誤って条件に含めるか、S001 を除外するなどの計算ミスが原因でこの値が出ます。 -
ウ(600)
誤り。600 は S001(100)+S003(300)+S005(200) の合算に見える値ですが、S005 は実際の在庫200でも出荷実績350のため条件を満たさず除外されます。出荷実績の判定ミスで発生する誤答です。 -
エ(700)
誤り。700 は S002(250)+S004(450) の合算です。これは SUM が存在しない(NULL)行を 0 とみなして WHERE (0 <= 300) を満たすと誤解した場合に得られ得る値ですが、標準SQLでは SUM が行なしで NULL になり、NULL <= 300 は UNKNOWN(偽扱い)となり除外されます。
よくある誤解
- 「SUM が行がなければ 0 になる」
実際は標準SQLの集計関数 SUM は該当行が無ければ NULL を返します(COALESCE 等で 0 に変えなければならない)。NULL と比較すると条件は真になりません。 - 「WHERE は集計後に効く」
単一の SELECT 内では WHERE は GROUP BY 前に適用され、HAVING が集計後の条件に使われます。ただし本問の WHERE は外側クエリであり、ビュー(集計済み結果)に対するフィルタなので集計後の行に作用します。この点を混同しやすいので注意してください。 - 「LEFT JOIN で NULL は自動的に 0 になる」
LEFT JOIN により右側の列が NULL になることはあるが、それを 0 とみなすのはデータベースが自動で行う処理ではありません。明示的に置換が必要です。
補足コラム
出荷実績がない商品も「出荷実績数 = 0」として扱いたい場合は、ビュー定義で NULL を 0 に置換しておくと便利です。例えば次のように COALESCE(または DBMS により NVL)を使います。
CREATE VIEW 商品別出荷実績 AS
SELECT
m.商品コード,
COALESCE(SUM(t.出荷数), 0) AS 出荷実績数,
m.在庫数
FROM
月末商品在庫 m
LEFT OUTER JOIN 当月商品出荷実績 t
ON m.商品コード = t.商品コード
GROUP BY
m.商品コード, m.在庫数;
このようにしておけば外側の WHERE で 0 <= 300 を満たす行も残り、条件に含めたいか否かを意図的に制御できます。
また、同じクエリを1つのSELECTで書く場合、集計後の条件は HAVING を使う点を覚えておいてください。
FAQ
Q1: SUM が NULL になるかどうかは DBMS による違いがありますか?
A1: 標準SQLでは集計対象行が無ければ NULL を返します。主要な商用・オープンソースDBでも同様です。動作に依存する振る舞いが心配なら COALESCE で明示的に扱ってください。
A1: 標準SQLでは集計対象行が無ければ NULL を返します。主要な商用・オープンソースDBでも同様です。動作に依存する振る舞いが心配なら COALESCE で明示的に扱ってください。
Q2: WHERE を HAVING に変えればどうなりますか?
A2: 同じSELECT内で集計結果に条件をかけたい場合は HAVING を使います。ビューを既に使っている場合、外側の WHERE はビューの結果に作用するため、実務ではどちらを使うかは構造によります。
A2: 同じSELECT内で集計結果に条件をかけたい場合は HAVING を使います。ビューを既に使っている場合、外側の WHERE はビューの結果に作用するため、実務ではどちらを使うかは構造によります。
Q3: NULL を 0 にする別の方法はありますか?
A3: COALESCE(SUM(...), 0) の他、DBMS 固有の NVL(Oracle)や IFNULL(MySQL)などがあります。
A3: COALESCE(SUM(...), 0) の他、DBMS 固有の NVL(Oracle)や IFNULL(MySQL)などがあります。
関連キーワード: SQL、LEFT OUTER JOIN、SUM、NULL、COALESCE、GROUP BY、WHERE、HAVING、集計順序

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

