DBデータベーススペシャリスト試験 午後Ⅰ

平成29年度春期 データベーススペシャリスト 午後Ⅰ 問3

事例を読んで設問の答えを考えてから、解説のポイントとIPA公式の解答例・採点講評で確認しましょう。

問題

問3 テーブル及びSQLの設計に関する次の記述を読んで、設問1、2に答えよ。 A社は、全国の主要都市に家電販売チェーン店を展開している。A社では、RDBMSの機能を用いて販売分析支援システム(以下、システムという)を運用しており、Fさんがテーブル及びSQLの設計を見直すことになった。 〔業務の概要〕 (1)店舗は、営業本部の下で全国展開され、店舗コードで識別される。 (2)店舗で販売を担当する社員は、いずれか一つの店舗に配属され、社員IDで識別される。各店舗には複数の社員が配属される。 (3)商品は、商品コードで識別される。 〔システムの概要〕 1.主なテーブル構造 主なテーブル構造を、図1に示す。ここで、テーブルの行は追加された順に並び、同じページに異なるテーブルの行が格納されることはない。また、索引のキー順に、ページ単位で順次又はランダムに磁気ディスク装置(以下、ディスクという)からバッファに読み込まれる。 図1 主なテーブル構造(一部省略) 2.システムの運用の概要 (1)各店舗は、閉店後の夜間に当日の売上明細ファイルを、システムに送信する。 (2)システムは、各店舗から送信された売上明細ファイルのデータを店舗コード別商品コード別に集計し、翌朝までに“月別売上”テーブルに反映させる。 (3)営業本部の担当者は、システムを用いて販売分析を行う。また、担当者は店舗の社員に電話をかけて販売状況を問い合わせることがある。 3.営業本部からの要望及び対応の方針 営業本部からの要望のうち、Fさんに対応を任せられた要望と、Fさんによる対応の方針は、次のとおりである。Fさんがこれらの方針に従って変更した二つのテーブル構造を、図2に示す。 要望1 売上データの分析を行うための照会の応答時間を改善してほしい。 方針1 “月別売上”テーブルを、“月別売上B”テーブルのように変更する。 要望2 社員連絡先の電話番号を3個以上登録できるようにしてほしい。 方針2 “社員連絡先”テーブルに新たな列を追加するのではなく、“社員連絡先B”テーブルのように変更する。 図2 変更した二つのテーブル構造(一部省略) 〔“月別売上”テーブルの構造の変更〕 Fさんは、“月別売上”テーブルの構造の変更を、次のように検討した。 1.“月別売上”テーブルには、行が主索引のキー順にロードされている。その全行をアンロードしたファイルを、“月別売上B”テーブルの構造に従って変換し、“月別売上B”テーブルに主索引のキー順にロードした。 2.RDBMSの機能を用いて、テーブルの統計情報を取得した。“月別売上”テーブルと“月別売上B”テーブルの統計情報及び索引定義情報を、表1に示す。 3.次の二つの分析処理を選び、照会の応答時間を評価した。その指標として、各分析処理に必要なディスクからの読込み行数及び読込みページ数を、表1の統計情報を基に比較した。 分析処理1 指定した1店舗について、任意の1年間の売上データを分析する。 分析処理2 指定した1商品について、任意の月の売上データを分析する。 表1 “月別売上”テーブルと“月別売上B”テーブルの統計情報及び索引定義情報 (1)表1の二つのテーブルでは、複数行を索引のキー順に読み込む場合、アクセス経路が【ア】索引のとき、ページは順次に読み込まれるが、アクセス経路が【イ】索引のとき、1行当たり1ページがランダムに読み込まれる。 (2)分析処理1では、分析に必要な“月別売上”テーブルの1店舗当たりの年間平均行数は、【ウ】行である。これらの行を、主索引を用いてディスクから読み込むとき、最小限【エ】ページ読み込む必要がある。 一方、“月別売上B”テーブルの1店舗当たりの年間平均行数は、指定した1年間が年をまたがなければ、【オ】行である。これらの行を、主索引を用いてディスクから読み込むとき、最小限【カ】ページを読み込めばよい。しかし、その1年間が年をまたがれば、読込みページ数は【キ】年間分の【ク】ページに増える。 (3)分析処理2では、分析に必要な行数は、二つのテーブルとも1商品コード当たり最大【ケ】行である。これらの行を、副次索引を用いてディスクから読み込むとき、最大【コ】ページ読み込む必要がある。 4.プログラム中のSQLへの影響を調べた。調べたのは、同じ年の二つの月、例えば、2017年1月と2017年2月の売上額の差を求めるSQLで、その構文を表2中のSQL1に示す。テーブル構造を変更した後で、SQL1と同じ結果行を得るために、実行の都度、比較する年月に対応したSQLの構文を組み立て、動的SQLで実行することにした。その構文を表2中のSQL2に示す。 表2 同じ年の二つの月の売上額の差を求めるSQLの構文(未完成) 〔“社員連絡先”テーブルの構造の変更〕 Fさんは、“社員連絡先”テーブルの構造の変更を、次のように検討した。 1.“社員連絡先”テーブルの電話番号1列と電話番号2列の値を調べたところ、プログラムの不備による次のような問題の行があることが分かった。 問題1 電話番号1列と電話番号2列は、異なる電話番号であるべきところ、同じ電話番号が設定されている行があった。 問題2 電話番号1列だけに電話番号を設定すべきところ、電話番号1列にNULLが、電話番号2列に電話番号が設定されている行があった。 問題3 電話番号が設定されている場合だけ行を登録すべきところ、電話番号1列と電話番号2列の両方にNULLが設定されている行があった。 2.問題1~3を防ぐには、“社員連絡先”テーブルに、図3に示す検査制約を定義すべきであった。ここで、検査制約は、次の①~④のいずれかの述語を組み合わせて指定する。 ① 電話番号1 IS NOT NULL ② 電話番号1 IS NULL ③ 電話番号2 IS NOT NULL ④ 電話番号2 IS NULL 図3 “社員連絡先”テーブルに定義すべきだった検査制約(未完成) 3.“社員連絡先B”テーブルの要件を、次のように整理した。 要件1 問題1~3を解決すること 要件2 社員1人当たりの電話番号を3個以上登録できること なお、同じ電話番号が複数の社員で使われることがある。 4.“社員連絡先B”テーブルの電話番号列にNOT NULL制約を定義し、テーブルに一意性制約を定義した。 5.要件1、2を満たすために、図4に示すINSERT文を用いて、“社員連絡先”テーブルから“社員連絡先B”テーブルに行を移行することにした。その移行試験を行ったときの、移行元である“社員連絡先”テーブルの問題1~3を含む行を表3に、移行先である“社員連絡先B”テーブルの行を表4に示す。ここで、表3及び表4の見出しは列名を表す。 図4 “社員連絡先B”テーブルに行を移行するINSERT文(未完成) 表3 移行元の行 表4 移行先の行(未完成) 設問1 〔“月別売上”テーブルの構造の変更〕について、(1)~(3)に答えよ。 (1)分析処理に関する記述中の【ア】~【コ】に入れる適切な字句を答えよ。 なお、索引のバッファヒット率は100%であり、ページ中の行をアクセスするとき、次にアクセスするページはバッファにないものとする。 (2)表2中の【a】、【b】に入れる適切な字句を答えよ。 (3)Fさんは、なぜ表2中のSQL2を動的SQLで実行することにしたのか。その理由を40字以内で述べよ。 設問2 〔“社員連絡先”テーブルの構造の変更〕について、(1)~(5)に答えよ。 (1)“社員連絡先B”テーブルの電話番号列にNOT NULL制約を定義した理由を、本文中の字句を用いて25字以内で述べよ。 (2)“社員連絡先B”テーブルの一意性制約に定義すべき列名又は列名の組合せを答えよ。ここで、主キー制約を除くこと。 (3)図3中の【c】~【e】に入れる適切な述語を、①~④の中からそれぞれ重複なく一つずつ選んで答えよ。 (4)図4中の【f】~【h】に入れる適切な述語を、(3)に倣って①~④の中からそれぞれ重複なく一つずつ選んで答えよ。 (5)表4に記入されている1行目の例に倣って、全ての結果行を埋めよ。ここで、行の並び順は問わない。また、表4の全ての行が埋まるとは限らない。
図1 主なテーブル構造(一部省略)。店舗、商品、月別売上、社員配属先、社員連絡先の主要テーブル構造を示す図。
図1 主なテーブル構造(一部省略)。店舗、商品、月別売上、社員配属先、社員連絡先の主要テーブル構造を示す図。
図2 変更した二つのテーブル構造(一部省略)。月別売上を月別売上Bへ、社員連絡先を社員連絡先Bへ変更した構造を示す図。
図2 変更した二つのテーブル構造(一部省略)。月別売上を月別売上Bへ、社員連絡先を社員連絡先Bへ変更した構造を示す図。
表1 “月別売上”テーブルと“月別売上B”テーブルの統計情報及び索引定義情報。二つの売上テーブルについて、行数、ページ当たり行数、列値個数、主索引、副次索引を比較する表。
表1 “月別売上”テーブルと“月別売上B”テーブルの統計情報及び索引定義情報。二つの売上テーブルについて、行数、ページ当たり行数、列値個数、主索引、副次索引を比較する表。
表2 同じ年の二つの月の売上額の差を求めるSQLの構文(未完成)。変更前SQL1と変更後SQL2の売上額差分検索を並べ、未完成部分を示したSQL構文表。
表2 同じ年の二つの月の売上額の差を求めるSQLの構文(未完成)。変更前SQL1と変更後SQL2の売上額差分検索を並べ、未完成部分を示したSQL構文表。
図3 “社員連絡先”テーブルに定義すべきだった検査制約(未完成)。電話番号1と電話番号2のNULL条件および相違条件を組み合わせる検査制約の未完成図。
図3 “社員連絡先”テーブルに定義すべきだった検査制約(未完成)。電話番号1と電話番号2のNULL条件および相違条件を組み合わせる検査制約の未完成図。
図4 “社員連絡先B”テーブルに行を移行するINSERT文(未完成)。旧テーブルの電話番号列から新テーブルへ行を移行する三つのSELECTとUNIONによるINSERT文。
図4 “社員連絡先B”テーブルに行を移行するINSERT文(未完成)。旧テーブルの電話番号列から新テーブルへ行を移行する三つのSELECTとUNIONによるINSERT文。
表3 移行元の行。社員E1からE5までの電話番号1と電話番号2の値を示す移行元データ表。
表3 移行元の行。社員E1からE5までの電話番号1と電話番号2の値を示す移行元データ表。
表4 移行先の行(未完成)。社員ID、表示順、電話番号の列を持つ移行先テーブルの未完成行表。
表4 移行先の行(未完成)。社員ID、表示順、電話番号の列を持つ移行先テーブルの未完成行表。
解き方のヒントを見る

変更前後の差分を軸に設計を検討する

構造変更を伴う設計の問題では、個々の用語の知識より先に、変更前と変更後で何が変わり何が変わらないのかを問題の記述から整理することが大切です。その差分を起点に、問われている箇所への影響を一つずつ確かめましょう。

この問題で問われていること

確認すべき観点は一つ、変更によって前提が崩れる箇所を特定することです。記述中の条件や制約が変更後も成り立つかを追い、その前提に依存している処理や設計判断がどこかを結び付けて考える姿勢が求められます。

視点

データベースの設計は、ある時点の構造やデータの状態を前提にして組み立てられています。構造を変更すると、その前提に依存していた部分が暗黙のうちに影響を受けることがあります。一般的な検討手順としては、まず変更の内容を正確に把握し、次にその変更に依存する要素を洗い出します。最後に、それぞれの要素について前提が維持されるかを問題の記述に照らして確かめます。自分の知識や一般論だけで判断せず、記述に示された条件を根拠にすることが重要です。

確認ポイント

  • 変更前の構造・条件と変更後の構造・条件を、問題の記述から対応付けて整理できているか
  • 問われている箇所が、変更によって失われる前提や新たに加わる前提に依存していないかを確かめたか
  • 判断の根拠を一般論ではなく、問題中に示された条件や記述に求めているか
正解と解説を見る

解説

繰返し項目を横持ちにするか縦持ちにするかという判断を題材にした問題です。月別売上テーブルを横持ちにすると、統計情報と索引のキー順から読込みページ数が変わることを見積もり、年月が列名になるため動的SQLが必要になることを押さえます。社員連絡先テーブルでは、横持ちのままだと検査制約で問題1~3を防ぐ必要があり、縦持ちに変えるならNOT NULL制約と一意性制約を定義したうえで、UNIONを使ってデータを移行します。この一連の流れを追う問題です。

問題の全体像

A社の販売分析支援システムで、Fさんが二つのテーブルを見直す事例です。要望1(照会の応答時間の改善)には、月別に1行ずつ持つ“月別売上”を、1年分の12か月を列として持つ横持ちの“月別売上B”に変えて対応します。要望2(電話番号を3個以上登録したい)には、電話番号1・電話番号2を列として持つ横持ちの“社員連絡先”を、表示順ごとに1行を持つ縦持ちの“社員連絡先B”に変えて対応します。出題趣旨では、横持ちと縦持ちそれぞれの長所・短所・制約を理解したうえでテーブルとSQLを設計する能力、テーブル構造の変更に伴うデータ移行を行う能力を問うとしています。採点講評では、全体として正答率は高かったものの、設問1(1)のケ・コと設問1(3)でつまずいた受験者が多かったと述べています。

設問1(1)(ア)

本文では、“月別売上”の行は主索引のキー順にロードされ、“月別売上B”にも主索引のキー順にロードしたと述べています。行の物理的な並びが主索引のキー順と一致しているので、主索引のキー順に複数行を読むと、隣り合うページを順番に読み込むことになります。公式解答例では「主」です。

設問1(1)(イ)

表1の副次索引は、売上年月(売上年)、商品コード、店舗コードの順にキーが定義されており、主索引の列の順番(年月、店舗、商品)とは異なります。このため副次索引のキー順は行の物理的な並びと一致せず、1行ごとに別のページをランダムに読み込むことになります。公式解答例では「副次」です。

設問1(1)(ウ)

表1で“月別売上”は360、000、000行あり、売上年月は60、店舗コードは200、商品コードは30、000の値を持ちます。60×200×30、000=360、000、000なので、全ての組合せに1行ずつ存在すると読み取れます。1店舗の1年間分は、30、000商品×12か月=360、000行です。公式解答例では360、000です。

設問1(1)(エ)

主索引の先頭列は売上年月、2番目の列は店舗コードです。そのため、1店舗の行が連続して並ぶのは同じ月の中だけで、1か月分30、000行が連続し、それが12か月分に分かれています。1ページ当たりの行数は100行なので、1か月分で300ページ、12か月で3、600ページを最小限読み込む必要があります。公式解答例では3、600です。

設問1(1)(オ)

“月別売上B”は売上年、店舗コード、商品コードの組合せごとに1行を持ち、12か月分の売上額と販売数を1行の列として保持します。年をまたがない1年間であれば、1店舗につき商品数と同じ30、000行です。公式解答例では30、000です。

設問1(1)(カ)

主索引は売上年、店舗コード、商品コードの順なので、同じ年の1店舗分30、000行は連続して格納されています。1ページ当たり30行なので、30、000÷30=1、000ページを順次に読み込めば足ります。公式解答例では1、000です。行数だけでなくページ数も“月別売上”の3、600ページから減る点が、横持ちの長所です。

設問1(1)(キ)

例えば2016年4月から2017年3月のように指定した1年間が年をまたぐと、売上年が異なる二つの行にデータが分かれます。このため2年分の行を読み込む必要があります。公式解答例では2です。

設問1(1)(ク)

1年分は1、000ページなので、2年分では1、000×2=2、000ページになります。公式解答例では2、000です。横持ちでは、分析する期間が行の区切り(年)と合わないと、読込み量が増えるという短所があります。

設問1(1)(ケ)

分析処理2は、1商品について任意の1か月分を分析します。“月別売上”では売上年月と商品コードを指定すると、店舗数と同じ200行になります。“月別売上B”でも売上年と商品コードを指定すると、店舗ごとに1行ずつの200行になります。公式解答例では200です。

設問1(1)(コ)

この処理では、年月(年)と商品コードが先頭にある副次索引を使います。副次索引のアクセスでは1行当たり1ページがランダムに読み込まれるので、200行に対して最大200ページを読み込みます。公式解答例では200です。採点講評では、アとイは正しく解答していながらケとコを誤った受験者が多く、ランダムにページを読み込む索引の理解が不十分だったと指摘しています。

設問1(2)(a)

SQL1は、自己結合を使って2017年2月の売上額(Y)から2017年1月の売上額(X)を引いています。“月別売上B”では同じ年の月別の売上額が1行の中に列として並んでいるので、結合せずに列どうしの差を求めれば同じ結果になります。公式解答例では「売上額2月 - 売上額1月」です。引く順番をSQL1(Y−X)と同じにすることに注意してください。

設問1(2)(b)

行を絞り込む条件は対象の年だけです。売上年はCHAR(4)型なので、公式解答例では「売上年 = '2017'」、またはパラメタを使った「売上年 = ?」としています。

設問1(3)

縦持ちの“月別売上”では、年月は売上年月列の値だったので、ホスト変数で指定できました。横持ちの“月別売上B”では、月は売上額1月、売上額2月のような列名に変わります。列名はホスト変数では指定できないため、静的SQLでは比較する年月の全ての組合せをあらかじめ用意しなければなりません。公式解答例では「比較する売上年月ごとに選択リストの列名を変更しなければならないから」としています。答案では、比較する年月によって選択リストの列名が変わる点を40字以内でまとめます。採点講評でも、年月が列値から列名に変わること、動的SQLなら実行の都度列名を変えて対応できることを理解してほしいと述べており、正答率が低かった設問です。

設問2(1)

問題3には「電話番号が設定されている場合だけ行を登録すべき」とあります。縦持ちの“社員連絡先B”では、1行が電話番号1件に対応するので、電話番号列がNULLの行は登録してはいけません。公式解答例では「電話番号が設定されている行だけを登録したいから」としています。本文中の字句を使い、25字以内で書きます。採点講評でも、問題3から、電話番号が設定されていない社員は“社員連絡先B”に登録されないことを読み取ってほしいと述べています。

設問2(2)

主キーは{社員ID、 表示順}なので、同じ社員が同じ電話番号を別の表示順で登録することは主キーでは防げず、問題1に当たる状態が起こり得ます。一方、本文には同じ電話番号が複数の社員で使われることがあるとあるので、電話番号だけに一意性制約を定義することはできません。公式解答例では「社員ID,電話番号」(順序は逆でもよい)です。

設問2(3)(c)

問題2と問題3から、電話番号1がNULLの行は、電話番号2の値にかかわらず許されません。したがって、ORでつないだ二つの条件の両方に「電話番号1 IS NOT NULL」が必要です。公式解答例ではc=①です。

設問2(3)(d)

一つ目の条件は、電話番号が2件ある場合を表します。電話番号2も値を持ち、かつ電話番号1と異なる必要があるので(問題1の防止)、「電話番号2 IS NOT NULL」を指定します。公式解答例ではd=③です。

設問2(3)(e)

二つ目の条件は、電話番号が電話番号1の1件だけの場合を表すので、「電話番号2 IS NULL」を指定します。公式解答例ではe=④です。これで、許される状態は、電話番号が2件で互いに異なる場合と、電話番号1だけに値がある場合の二つに限られます。

設問2(4)(f)

図4の一つ目のSELECTは、電話番号1を表示順1として移行します。NOT NULL制約に違反しないよう、電話番号1が値を持つ行だけを対象にします。公式解答例ではf=①です。

設問2(4)(g)

三つ目のSELECTは、電話番号2を表示順1として移行します。これは問題2の行、つまり電話番号1がNULLで電話番号2だけに値がある行を正しい形に直す処理です。そのため、条件の一つは「電話番号1 IS NULL」になります。公式解答例ではgとhは順不同で、②と③です。

設問2(4)(h)

もう一つの条件は「電話番号2 IS NOT NULL」です。これがないと、問題3の行(両方ともNULL)の電話番号2がNULLのまま移行されてしまいます。公式解答例ではgとhは順不同で、②と③です。

設問2(5)

表3の各行を、図4の三つのSELECTの条件に当てはめます。E1(1111、3333)は、一つ目のSELECTで(E1、 1、 1111)、二つ目のSELECTで(E1、 2、 3333)になります。E2(2222、2222)は、一つ目のSELECTで(E2、 1、 2222)になります。二つ目のSELECTの条件「電話番号1 <> 電話番号2」は2222と2222が等しいので偽になり、表示順2の行は作られません。つまり、E2が1行だけになるのは移行SQLの条件によるもので、一意性制約が行をまとめたわけではありません。E3(3333、NULL)は、一つ目のSELECTで(E3、 1、 3333)になります。二つ目のSELECTは、NULLとの比較が不明になるので選択されません。E4(NULL、4444)は、一つ目と二つ目のSELECTでは選択されず、三つ目のSELECTで(E4、 1、 4444)になります。E5(NULL、NULL)は、どのSELECTにも選択されません。公式解答例では、E1-1-1111、E1-2-3333、E2-1-2222、E3-1-3333、E4-1-4444の5行で、表4の最後の1行は空欄です。E1とE3が同じ3333を持っていても、社員IDが異なるので{社員ID、 電話番号}の一意性制約には違反しません。

学習のポイント

索引のキー順と物理的な行の並びの関係から読込みページ数を見積もる手順、横持ち・縦持ちそれぞれの長所と短所、NULLを含む述語の評価、移行SQLを行ごとに追って確かめる方法を重点的に学習してください。

出典:独立行政法人 情報処理推進機構(IPA)平成29年度春期 データベーススペシャリスト試験 午後Ⅰ 問3(公式資料:問題冊子(PDF) / 解答例 / 採点講評)

関連する過去問一覧

IPA Advancedは非公式の学習サイトです。解説にはAIによる補助生成を含む場合があります。公式の問題冊子・解答例・採点講評を優先し、誤りは確認後に訂正します。運営・編集方針