データベーススペシャリスト 2013年 午後1 問02
受注管理システムのデータベース設計に関する次の記述を読んで、設問1〜3に答えよ。
A社は、個人宅を訪問し、主にキッチン、浴室、洗面所、トイレなどの清掃をサービスとして提供する業者である。 A社では、受注管理システムを新たに構築することになり、B君がデータベース設計を任された。
〔業務概要〕
1.組織の特性
(1) 地域ごとに店舗があり、本店及び各店舗はそれぞれ店舗番号で一意に識別される。
(2) 本店は顧客からの引合いを受け付け、各店舗は引合いのあった顧客の見積りを行い、注文が確定した後、サービスを実施する。
2.会員の特性
顧客は、最初の注文時に会員登録される。 会員は、会員番号で一意に識別される。
3.サービスの特性
(1) サービスは、サービスコードで一意に識別される。
(2) サービスには、個別サービス、セットサービス及びオプションサービスの3種類があり、サービス区分でどの種類のサービスかが識別される。
① 個別サービスとは、キッチン清掃、レンジフード清掃、浴室清掃など、1か所の清掃を指す。 個別サービスのサービス内容、標準価格、標準作業時間数は決まっている。 個別サービスの例を表1に示す。
② セットサービスとは、個別サービスを複数組み合わせたもので、個別サービスそれぞれの標準価格の合計よりも割安な価格で提供する。 セットサービスに対して、選択可能な個別サービス群、選択可能数、標準価格は決まっている。一つの個別サービスは、複数の異なるセットサービスに組み込まれることがある。セットサービスの例を表2に示す。
③ オプションサービスとは、会員の依頼によって個別サービスに追加する清掃で、単独では提供しない。 オプションサービスのサービス内容、適用可能な個別サービス、標準価格、標準作業時間数は決まっている。一つのオプションサービスを適用できる個別サービスは、一つだけである。 一つの個別サービスに対して、複数のオプションサービスを追加できる。 セットサービスで選択した個別サービスに対しても、オプションサービスを追加できる。 オプションサービスの例を表3に示す。



4.注文の特性
(1) 注文は、注文番号で一意に識別される。
(2) 注文にはスポット注文と継続注文があり、注文区分で識別される。
① スポット注文とは、1回だけ清掃を行うケースの注文である。
② 継続注文とは、同じ清掃を複数回にわたって行うケースの注文である。
・会員は、期間、回数及び曜日を選択する。
・会員は、期間と回数について、24週間に6回,48週間に6回,48週間に12回など、あらかじめ決められた組合せの中から選択する。
・期間、回数、曜日の組合せは、継続パターンコードで識別される。また、それによって継続割引率は異なる。
(3) 一つの注文で、複数のサービスを指定できる。また、個別サービスとセットサービスを一緒に指定することもできる。
5.引合い、見積り、注文の確定の流れ
(1) 本店で受け付けた引合いは、地域ごとの店舗に割り当てられる。割り当てられた店舗は、会員宅を訪問して見積りを行う。
(2) 見積りによって、サービスごとの実施項目、適用価格が確定する。継続注文の場合、この確定内容は、2回目以降も継続する前提である。適用価格は、標準価格と異なる場合がある。
(3) 見積りにおいて、予定年月日、予定開始時刻、予定終了時刻を決定する。継続注文の場合、予定開始時刻と予定終了時刻は2回目以降もこの決定が適用されるが、予定年月日は初回だけに適用される。
(4) 見積り結果は、セットサービスで選択した個別サービス、及び個別サービスに追加したオプションサービスの対応関係が分かるように、サービス名の前に記号を付け、関係するサービスを並べて表示する。 また、同一の清掃を複数箇所に対して行う場合、それぞれを識別できるようにするために、実施場所に、所在を表示する。 見積り結果の例を図1に示す。
(5) 会員が見積り結果を確認し、同意すれば注文が確定する。

6.実施の流れ
(1) 会員宅を訪問して注文内容に従って清掃を行う単位を、“実施”と呼ぶ。 スポット注文では1回の注文で1回の実施が発生し、継続注文では1回の注文で複数回の実施が発生する。
(2) 1回の実施に対して、一意となる実施番号が付与される。 1回の実施には一つ又は複数のサービスが含まれ、サービスごとに実施明細番号が付与される。
(3) 注文確定によって、スポット注文と継続注文の初回の実施予定を決定し、登録する。 その際、個別サービス、オプションサービスごとに、予定作業時間数を割り当てる。
(4) 継続注文の2回目以降は、実施時に次回の予定年月日を決め、その時点で次回の実施予定を登録する。
(5) 1回の実施で予定していた、全ての清掃が終了した時点で、実施年月日、実施開始時刻、実施終了時刻を登録する。 また、個別サービス、オプションサービスごとに実施作業時間数を登録する。
(6) サービスごとの実施作業時間数は、サービスの作業改善、標準作業時間数の見直しのために、過去の実績を分析する場合に照会する。
〔データベースの設計〕
B君は、現在の業務概要と次の方針に基づいて、テーブル構造を図2のように設計することにした。
(1) セットサービスで選択された個別サービスも、単品で選択された個別サービスも、“注文明細” テーブルには同様の形式で格納する。
(2) 注文の確定時に“注文” テーブル及び “注文明細” テーブルに行を作成する。実施予定登録時に “実施” テーブル及び “実施明細” テーブルに行を作成する。
(3) “実施” テーブルの行から対応する “注文” テーブルの行、“実施明細” テーブルの行から対応する “注文明細” テーブルの行を特定するために、外部キーを設定する。
↩設問1(1) ↩設問1(2) ↩設問1(3) ↩設問2(1) ↩設問2(2) ↩設問3(2)
↩設問1(1) ↩設問1(2) ↩設問1(3) ↩設問2(1) ↩設問2(2) ↩設問3(2)〔継続注文の変更〕
検討中のテーブル構造では、継続注文について、初回の実施後、継続する2回目以降にオプションサービスの追加及び取消しを行いたくても対応できない。この点について、会員からの要望を満たせていないことが判明した。 そこで、B君は、2回目以降の実施に対して、オプションサービスの追加及び取消しを行えるように、次の対応を考えた。
(1) 次回の実施予定を決定するときに、変更の要望を確認し、変更があれば必要な見積りを実施して、適用価格と変更の要望に伴う予定開始時刻及び予定終了時刻の変更を決定する。
(2) 当初の注文確定時点の情報を含め、変更履歴を注文変更年月日ごとに保存する。
解答に当たっては、巻頭の表記ルールに従うこと。
なお、テーブル構造の表記は、“関係データベースのテーブル (表) 構造の表記ルール” を用いること。 さらに、主キー及び外部キーを明記せよ。
また、新たに追加するテーブル名及び列名は、本文中で与えられた語句を用いて適切な名称とすること。
(1)
“サービス” テーブルには、セットサービス、個別サービス及びオプションサービスの3種類のサービスが格納される。 そこで、“サービス” テーブルを、3種類のサービスに共通の列をもつ“サービス共通” テーブルと、各サービスに固有の列をもつテーブルに分割することにした。 列が冗長にならないように、各テーブルの構造を記述せよ。
模範解答
サービス共通(サービスコード、サービス区分、サービス名、標準価格)
個別サービス(サービスコード、サービス内容、標準作業時間数)
セットサービス(サービスコード、個別サービス選択可能数)
オプションサービス(サービスコード、サービス内容、標準作業時間数、個別サービスコード)
解説
解答の導き方
- 問題文から分かることを整理する
- 本文には「“サービス” テーブルには、 セットサービス、 個別サービス及びオプションサービスの3種類のサービスが格納される」とあるので、サービスは3種類に分類され、それぞれ固有の属性を持ちうることが分かります。
- また「サービスは、サービスコードで一意に識別される」とあるため、サービス共通の主キーはサービスコードでよいことが分かります。
- 表1~表3の例を見ると、個別サービスは「サービス内容」「標準価格」「標準作業時間数」を持ち、セットサービスは「選択可能な個別サービス群」「選択可能数」「標準価格」を持ち、オプションサービスは「サービス内容」「適用可能な個別サービス」「標準価格」「標準作業時間数」を持つことが分かります(例えば本文に「個別サービスのサービス内容、標準価格、標準作業時間数は決まっている」「セットサービスに対して、選択可能な個別サービス群、選択可能数、標準価格は決まっている」「オプションサービスのサービス内容、適用可能な個別サービス、標準価格、標準作業時間数は決まっている」とある)。
- 分割方針の論理的根拠
- 共通属性は一つのテーブルにまとめ、各種別固有の属性は別テーブルに分ける(正規化、冗長排除)。ここで共通属性として「サービスコード」「サービス区分」「サービス名」「標準価格」が妥当である。理由は各種別の例すべてに「サービス名」「標準価格」が登場し、サービスごとの識別子が「サービスコード」であるためです。
- 個別サービスとオプションサービスは双方で「サービス内容」「標準作業時間数」を持つが、オプションには「適用可能な個別サービス(個別サービスコード)」という依存先があるため、オプション専用テーブルを用意して個別サービスとの参照関係を明示する。
- セットサービスは「個別サービス選択可能数」などセット固有の情報を持つ。どの個別サービスが選択可能群に含まれるかは、図2に既にある“セット組合せ”テーブルで表されているので、この設問で新たに設計する必要はない。
- 主キー/外部キーの扱い方(重要)
- 下位表(個別サービス、セットサービス、オプションサービス)のサービスコードは、それぞれの表の主キーであると同時に、サービス共通.サービスコード を参照する外部キーである(PK=FK)。これにより「あるサービスコードがサービス共通に必ず1行あり、かつそのサービスはちょうど一つの下位表に属する」という1:1の関係を確実に表現できる。
- セットと個別サービスの対応(多対多)は、図2の“セット組合せ”テーブルがそのまま担う。
- 設問の範囲
- 設問は“サービス”テーブルの分割だけを問うている。“セット組合せ”や“継続パターン”は図2のままでよい(継続パターンは設問1(2)(3) のとおり第3正規形である)。
以上の考え方から、下に各テーブル構造と主キー/外部キーを明記する。
(表記ルール:主キーは下線表示、外部キーは参照先を明示)
サービス共通(サービスコード、サービス区分、サービス名、標準価格)
- 主キー:サービスコード
- 注:すべてのサービス(セット/個別/オプション)に共通する属性を保持する。
個別サービス(サービスコード、サービス内容、標準作業時間数)
- 主キー:サービスコード
- 外部キー:サービスコード → サービス共通.サービスコード(PK=FK、1:1)
- 注:個別サービス固有の情報を保持する。
セットサービス(サービスコード、個別サービス選択可能数)
- 主キー:サービスコード
- 外部キー:サービスコード → サービス共通.サービスコード(PK=FK、1:1)
- 注:セット固有の属性のみ保持し、構成する個別サービスは別表で管理する。
オプションサービス(サービスコード、サービス内容、標準作業時間数、個別サービスコード)
- 主キー:サービスコード
- 外部キー:サービスコード → サービス共通.サービスコード(PK=FK、1:1)
- 外部キー:個別サービスコード → 個別サービス.サービスコード(オプションが適用できる個別サービスを参照、1:N)
- 注:本文にある「一つのオプションサービスを適用できる個別サービスは、一つだけである」を反映し、個別サービスコードは単値で参照する。
補足(他のテーブル)
- セットサービスで選択可能な個別サービスの組合せは、図2の“セット組合せ”テーブルで管理する(分割後は、セットサービスコードがセットサービスを、個別サービスコードが個別サービスを参照する)。
以上により、属性の重複を避けつつ、参照整合性(どの列がどのテーブルを参照するか)を明確にした設計になる。
誤りやすいポイント
- 下位表(個別/セット/オプション)のサービスコードを単純に主キーにするだけで、サービス共通との参照関係(PK=FKの1:1)を書き落とす。必ず「下位表のサービスコードはサービス共通.サービスコード を参照する外部キーでもある」と明示する。
- セットと個別の対応を表すテーブルで、どちらの列がどちらのテーブルを参照するかを誤る(両方ともセットサービスを参照するような誤り)。セット組合せではセットサービスコード→セットサービス、個別サービスコード→個別サービス にそれぞれ参照させること。
- オプションサービスの「適用個別サービス」は単一の個別サービスを参照する点を見落とし、誤って多値扱いにする。本文に「一つのオプションサービスを適用できる個別サービスは、一つだけである」とある。
- 設問の範囲外の“継続パターン”まで分割してしまう。継続パターンは {期間、回数、曜日} を候補キーとする第3正規形であり(設問1(2)(3))、分割は不要。
- サービス共通に「サービス内容」や「標準作業時間数」を入れてしまうと、セットサービスでNULLが多発する設計になる(セットはこれらを持たない場合がある)。固有属性は下位表へ。
FAQ
Q: 個別サービスとオプションサービスで「サービス内容」「標準作業時間数」が同じなら、まとめてしまってもよいですか?
A: 実務上は似た属性があっても、オプションは「適用個別サービス」を必ず持つ点で意味が異なるため分けるべきです。共通テーブルに入れるとセットサービスで不要な列がNULLになりやすく冗長・扱いにくくなります。
A: 実務上は似た属性があっても、オプションは「適用個別サービス」を必ず持つ点で意味が異なるため分けるべきです。共通テーブルに入れるとセットサービスで不要な列がNULLになりやすく冗長・扱いにくくなります。
Q: セットサービスに含まれる個別サービスの「順序」や「優先度」が必要になった場合はどうしますか?
A: セット組合せテーブルに順序や優先度の列を追加します(例:セット組合せ(セットサービスコード、個別サービスコード、順序))。追加属性は結合テーブル側で管理するのが自然です。
A: セット組合せテーブルに順序や優先度の列を追加します(例:セット組合せ(セットサービスコード、個別サービスコード、順序))。追加属性は結合テーブル側で管理するのが自然です。
関連キーワード: 正規化、主キー、外部キー、スーパータイプ・サブタイプ、結合テーブル
(2)
“継続パターン” テーブルの候補キーを全て答えよ。なお、複数の列から構成される候補キーは{ }でくくること。
模範解答
継続パターンコード、{期間、回数、曜日}
解説
解答の論理構成
- テーブル属性の整理
“継続パターン” テーブルは【図2】に示す
「継続パターンコード」「期間」「回数」「曜日」「継続割引率」
の5列で構成されています。 - 一意性を示す業務記述
【問題文】4.(2)② に
「期間、回数、曜日の組合せは、継続パターンコードで識別される。」
とあるため、 ・継続パターンコード は当然一意(候補キー①)。
・逆に 期間+回数+曜日 も1行を一意に決定(候補キー②)。 - 他列はキーにならない
継続割引率 は割引率を示す属性であり、同じ割引率が複数行に出現し得るため一意性を担保しません。 - よって候補キーは2つ
① 継続パターンコード
② {期間、回数、曜日}
誤りやすいポイント
- 継続割引率 を含めて {期間、回数、曜日、継続割引率} としてしまう。
- 「識別される」という文言を見落とし、複合キーを導けない。
- 主キーと候補キーの違いを混同し、「主キーは1つだから候補キーも1つ」と誤解する。
FAQ
Q: 候補キーと主キーの違いは何ですか?
A: 候補キーは行を一意に識別できる列(または列集合)の候補全てを指し、その中から実際にテーブル設計で選択・採用したものが主キーです。
A: 候補キーは行を一意に識別できる列(または列集合)の候補全てを指し、その中から実際にテーブル設計で選択・採用したものが主キーです。
Q: 継続割引率 が同じ行が複数あってはいけないのですか?
A: いいえ、一意性は要件にありません。同じ割引率でも期間や回数が異なれば別レコードになります。
A: いいえ、一意性は要件にありません。同じ割引率でも期間や回数が異なれば別レコードになります。
Q: 複合キーを書く順序は評価に影響しますか?
A: 成分が同じなら順序は評価に影響しませんが、答案では問題文に従って「{期間、回数、曜日}」と記述すると誤解が生じにくいです。
A: 成分が同じなら順序は評価に影響しませんが、答案では問題文に従って「{期間、回数、曜日}」と記述すると誤解が生じにくいです。
関連キーワード: 候補キー、複合キー、関数従属、正規化
(3)
“継続パターン” テーブルは、第1正規形、第2正規形、第3正規形のうち、どこまで正規化されているか。 また、部分関数従属性、推移的関数従属性の有無を、“あり” 又は “なし”で答えよ。“あり” の場合は、その関数従属性の具体例を、次の表記法に従って示せ。


模範解答
正規形:第3正規形
部分関数従属性の有無:なし
推移的関数従属性の有無:なし
解説
解答の論理構成
- 候補キーの確認
“継続パターン” テーブルの列は 継続パターンコード、期間、回数、曜日、継続割引率 です(図2は未完成で下線はありません)。設問1(2) のとおり、候補キーは「継続パターンコード」と {期間、回数、曜日} の二つです。継続パターンは期間・回数・曜日の組合せごとに一つ定義され、継続パターンコードで識別されるからです。 - 関数従属性の列挙
継続パターンコード → 期間、回数、曜日、継続割引率
{期間、回数、曜日} → 継続パターンコード、継続割引率 - 第1正規形の判定
すべての列は原子値で繰返し項目も無いので第1正規形を満たします。 - 第2正規形の判定
非キー属性は継続割引率だけです。継続割引率は {期間、回数、曜日} の一部(例えば期間と回数だけ)で決まるわけではなく、組合せ全体で決まるので、部分関数従属性はありません。 - 第3正規形の判定
非キー属性は継続割引率の一つだけなので、非キー属性を経由した推移的関数従属性はありません。よって第3正規形です。 - まとめ
・正規形:第3正規形
・部分関数従属性:なし
・推移的関数従属性:なし
誤りやすいポイント
- 「複合キーかどうか」を確認せずに自動的に部分関数従属性があると決めつける。
- {期間、回数、曜日} も候補キーであることを見落とし、継続パターンコードだけで判定してしまう。
- 非キー属性同士を “常識的に関連がありそう” という感覚で結び付け、推移的関数従属性と誤認する。
FAQ
Q: 「第2正規形=複合キーでないと関係ない」と覚えていて良いですか?
A: 候補キーが単一列だけなら部分関数従属性は生じませんが、このテーブルのように複数列の候補キー({期間、回数、曜日})もある場合は、その一部で非キー属性が決まらないかを確認する必要があります。
A: 候補キーが単一列だけなら部分関数従属性は生じませんが、このテーブルのように複数列の候補キー({期間、回数、曜日})もある場合は、その一部で非キー属性が決まらないかを確認する必要があります。
Q: 「曜日」や「期間」などを別テーブルに分割する必要はありますか?
A: 正規化の観点では必要ありません。現在の依存関係では、どちらの候補キーからも全ての列が決まり、第3正規形に達しているためです。
A: 正規化の観点では必要ありません。現在の依存関係では、どちらの候補キーからも全ての列が決まり、第3正規形に達しているためです。
Q: もし将来「継続割引率」が “期間×回数” で決まる仕様に変わったら?
A: その時点で「期間、回数 → 継続割引率」という部分関数従属性(候補キー {期間、回数、曜日} の一部による従属)が発生するため、第3正規形を維持するにはテーブル分割が必要になります。
A: その時点で「期間、回数 → 継続割引率」という部分関数従属性(候補キー {期間、回数、曜日} の一部による従属)が発生するため、第3正規形を維持するにはテーブル分割が必要になります。
関連キーワード: 正規化、主キー、部分関数従属性、推移的関数従属性、第3正規形
(1)
注文明細のサブタイプ構造を図3に示す。この3種類のサブタイプは、一つの注文の中で対応関係をもち得る。 その対応関係を示すリレーションシップを図3に記入せよ。 その場合、対応関係にゼロを含むか否かを区別して表現する場合の表記ルールを用いること。


模範解答

解説
解答の導き方
まず、図3は「注文明細」のサブタイプ構造(「セットサービス 注文明細」「個別サービス 注文明細」「オプションサービス 注文明細」)を示しているので、各サブタイプ間の「一つの(ある)サブタイプの注文明細が、他のサブタイプの注文明細と何件対応するか(最小・最大)」を、問題文の業務記述から決めます。
- セットサービス と 個別サービス の関係を決める根拠
- 問題文に「セットサービスとは、個別サービスを複数組み合わせたもので」とあり、セットは個別サービスの集合であることが明示されています。
- 図1の見積り例では、セットサービス(例:水まわり3点セット)に続いて「◆」で示された個別サービスの注文明細が並んでおり、セット注文明細の下に複数の個別注文明細が対応している表示になっています(図1ではセットの直下に個別がぶら下がっている)。
これらから、1つのセットサービス 注文明細に対して対応する個別サービス 注文明細は「1件以上」である必要があることが分かります(少なくとも1件の個別注文明細がなければセットとして成立しないため)。よってセット→個別の個別側の多重度は1..* です。
一方、個別サービスは単品で選択されることがあり「一つの注文で、複数のサービスを指定できる。また、個別サービスとセットサービスを一緒に指定することもできる」とあるため、ある個別サービス注文明細が「セットに属する」かどうかは任意です(属する場合はそのセットの一部、属さない場合は単品)。したがって個別側から見たセット側への参照は0..1(「属さない(0)」か「あるセットに属する(1)」)になります。
(注:サービス定義レベルで「一つの個別サービスは、複数の異なるセットサービスに組み込まれることがある」とあるのはカタログ設計上の関係であり、注文内の注文明細レコードが同一注文で複数のセットに同時に属することを意味しない点に注意します。)
- 個別サービス と オプションサービス の関係を決める根拠
- 問題文に「オプションサービスとは、会員の依頼によって個別サービスに追加する清掃で、単独では提供しない。」および「一つのオプションサービスを適用できる個別サービスは、一つだけである。」「一つの個別サービスに対して、複数のオプションサービスを追加できる。」とあります。
これらから、オプション注文明細は必ずどこかの個別サービス注文明細に紐づく必要があり(単独では存在しない)、その紐づき先は「ちょうど1件」であるためオプション側の多重度は1..1です。逆に、ある個別サービス注文明細はオプションを付けないこともあり得る一方で複数付けられるため、個別側から見たオプション側の多重度は0..* となります。図1の例(個別の下に「>>」で示されたオプションがぶら下がっている)もこの構造を裏付けます。
- 図3へ記入する最終的な多重度(言葉での記述)
- セットサービス 注文明細 — 個別サービス 注文明細
- 1つのセットサービス 注文明細 に対応する個別サービス 注文明細 は1以上(1..*)
- 1つの個別サービス 注文明細 が所属するセットサービス 注文明細 は0または1(0..1)
- 個別サービス 注文明細 — オプションサービス 注文明細
- 1つの個別サービス 注文明細 に対応するオプションサービス 注文明細 は0以上(0..*)
- 1つのオプションサービス 注文明細 は必ず1つの個別サービス 注文明細 に対応する(1..1)
図3に書き込む際は、各関係に対して上記の最小・最大(0か1か、1以上か)を明示してください。以上が図3に記入すべきリレーションシップの導出過程と結論です。
誤りやすいポイント
- 「セットサービスは複数の個別サービス」を見て、個別側の最小値を0としてしまう誤り。セットが存在する以上、そのセットに対応する個別注文明細は少なくとも1件必要です(表現は通常1..*)。
- 「一つの個別サービスは複数のセットに組み込まれることがある」というカタログ記述を、注文内の注文明細間で「個別注文明細が同時に複数のセット注文明細に属する」と誤解する点。ここでの「一つの個別サービス」はサービス種別(カタログ上の概念)であり、注文内の注文明細レコードは一意で、同時に複数のセットに属することは想定しません。
- オプションをオプション側から「0..1」にしてしまう誤り。オプションは「単独では提供しない」ため、オプション注文明細は必ずどこかの個別注文明細に紐づき、個別側への参照は必須(1)。
- 図に記入する記号(ゼロを含むか否か)を曖昧にしてしまう点。設問は「ゼロを含むか否か」を区別することを求めているので、必ず0または1の最小値を明示してください。
FAQ
Q: セットサービスは「複数組み合わせ」とあるので多重度の下限は2にすべきではありませんか?
A: カタログ上は選択可能数が2以上の制約があることが多いですが、サブタイプ間の基本的な多重度を図示する際は「少なくとも1件存在する」ことを表す1..* を用いるのが一般的です。実際の「選択可能数(2や3など)」はサービス定義(カタログ)の属性で管理され、注文明細の関係図では1..* と記述すれば要件を満たします。
A: カタログ上は選択可能数が2以上の制約があることが多いですが、サブタイプ間の基本的な多重度を図示する際は「少なくとも1件存在する」ことを表す1..* を用いるのが一般的です。実際の「選択可能数(2や3など)」はサービス定義(カタログ)の属性で管理され、注文明細の関係図では1..* と記述すれば要件を満たします。
Q: 「一つの個別サービスは、複数の異なるセットサービスに組み込まれることがある」とありますが、注文明細で個別注文明細が複数のセット注文明細に属する設計は必要ですか?
A: いいえ。該当記述はサービスの種類(カタログ)レベルの話であり、注文内の注文明細レコードは1つの行が同時に複数のセットに所属する構造にはしません。注文単位では個別注文明細は「その注文内で」最大1つのセットに紐づく(0または1)という前提で設計します。
A: いいえ。該当記述はサービスの種類(カタログ)レベルの話であり、注文内の注文明細レコードは1つの行が同時に複数のセットに所属する構造にはしません。注文単位では個別注文明細は「その注文内で」最大1つのセットに紐づく(0または1)という前提で設計します。
Q: 図3にはどのように記号で書けばよいですか?
A: 最小値が0の端には「0」を含む表記(○や0)、最小値が1の端には「1」を示す表記(●や1)、最大が多を示す側にはや爪足(crow's foot)等で1.. や0..* を明示してください。本文の論理(上記の1..* / 0..1 / 0..* / 1..1)を必ず示すことが重要です。
A: 最小値が0の端には「0」を含む表記(○や0)、最小値が1の端には「1」を示す表記(●や1)、最大が多を示す側にはや爪足(crow's foot)等で1.. や0..* を明示してください。本文の論理(上記の1..* / 0..1 / 0..* / 1..1)を必ず示すことが重要です。
関連キーワード: スーパタイプ/サブタイプ、カーディナリティ、多重度(0..1, 1..*)、合成(コンポジション)、参照整合性
(2)
(1)で答えたリレーションシップを成り立たせるために、現在の“注文明細”テーブルに列を二つ追加することにした。 それらの列に設定する値の意味を、具体的にそれぞれ40字以内で述べよ。
模範解答
①・選択された個別サービスの元となったセットサービスの注文明細番号
②・追加されたオプションサービスの元となった個別サービスの注文明細番号
解説
解答の導き方
-
要件の整理
問題文の設計方針に「セットサービスで選択された個別サービスも、単品で選択された個別サービスも、 “注文明細” テーブルには同様の形式で格納する。」とあります。これにより、セットで選んだ個別サービスも個別に選んだ個別サービスも同一の注文明細テーブルの行で扱う必要があると分かります。さらに見積りの説明に「見積り結果は、セットサービスで選択した個別サービス、及び個別サービスに追加したオプションサービスの対応関係が分かるように、サービス名の前に記号を付け、関係するサービスを並べて表示する。」とあり、セット→個別、個別→オプションという親子関係を保持する必要があることが明確です。 -
図からの重要な前提(参照方法の決定)
図2を見ると、注文明細の主キーは {注文番号, 注文明細番号} です(両方に下線)。親子関係にある明細(セットサービスとそれから選択された個別サービス、個別サービスとそれに追加されたオプションサービス)は、いずれも同じ注文の明細なので、親行の注文番号は子行の注文番号と同じです。したがって、親行を指すには、親行の「注文明細番号」を格納する列を追加すれば足ります。 -
列の意味決定の論理展開
- 図3のサブタイプ構造に対応して、注文明細内の「セットサービス注文明細」→「個別サービス注文明細」および「個別サービス注文明細」→「オプションサービス注文明細」という2種類の親子リンクを表現する必要があります。
- それぞれの子行が参照すべき親は親行の「注文明細番号」であるため、追加する2列は「親注文明細番号(セット由来を指す列)」と「親注文明細番号(個別由来を指す列)」のように、親の注文明細番号を格納する役割になります。非該当の場合はNULLを許容し、各列は自分の行の注文番号と組み合わせて注文明細を参照する外部キーとし、参照整合性を保ちます。
-
解答(列に設定する値の意味)
①・選択された個別サービスの元となったセットサービスの注文明細番号
②・追加されたオプションサービスの元となった個別サービスの注文明細番号
誤りやすいポイント
- 親を指す列に注文番号まで含めようとする。親行は同じ注文の明細なので、注文番号は自分の行の注文番号と同じであり、追加するのは注文明細番号を格納する列で足ります。
- 親子関係を表すのに1列にまとめてしまい、親の種別(セットか個別か)を別途判定しなければならなくなる設計にする。
- 追加列をNOT NULLにしてしまい、セット行や単品行で値を持たないケースを扱えなくする。
- 追加列に外部キー制約を設定しないまま運用すると、存在しない注文明細番号を参照するダングリング参照が発生する。
- 親子方向を逆に設計してしまい(親に子IDを列挙する等)、行の挿入・更新・削除や検索が複雑になる。
FAQ
Q: なぜ2列必要で、1列の「親注文明細番号」ではだめですか?
A: 1列でも親の注文明細番号を格納すれば参照自体は可能ですが、親の種類(セット由来か個別由来か)を別に判定する必要が生じ、可読性・運用性・参照整合性の管理が煩雑になります。設問の意図どおり明示的に2種類の元関係を残すほうが設計として分かりやすく安全です。
A: 1列でも親の注文明細番号を格納すれば参照自体は可能ですが、親の種類(セット由来か個別由来か)を別に判定する必要が生じ、可読性・運用性・参照整合性の管理が煩雑になります。設問の意図どおり明示的に2種類の元関係を残すほうが設計として分かりやすく安全です。
Q: 実施明細など他テーブルから注文明細を参照するときはどのキーを使うべきですか?
A: 図2の定義どおり注文明細の主キーは {注文番号, 注文明細番号} なので、他テーブルはこの組を外部キーとして参照します(図2の実施明細も 注文番号, 注文明細番号 をもっています)。
A: 図2の定義どおり注文明細の主キーは {注文番号, 注文明細番号} なので、他テーブルはこの組を外部キーとして参照します(図2の実施明細も 注文番号, 注文明細番号 をもっています)。
Q: 追加した列にはどんな制約を付けるべきですか?
A: 各列は、自分の行の注文番号と組み合わせて注文明細(注文番号, 注文明細番号)を参照する外部キー制約を設定し、該当しない行ではNULLを許容します。削除時の扱い(ON DELETE RESTRICTかNO ACTION等)は業務ルールに従って決めます。
A: 各列は、自分の行の注文番号と組み合わせて注文明細(注文番号, 注文明細番号)を参照する外部キー制約を設定し、該当しない行ではNULLを許容します。削除時の扱い(ON DELETE RESTRICTかNO ACTION等)は業務ルールに従って決めます。
関連キーワード: リレーショナルデータベース、外部キー、参照整合性、再帰的参照、サブタイプ化
設問3:注文と実施の管理について(1)、(2)に答えよ。
問題文を見る(1)
“実施明細” テーブルの行は “注文明細”テーブルの行に基づいて作成される。その際に、“実施明細” テーブルに反映する必要がない “注文明細” テーブルの行がある。 その行を15字以内で述べよ。 また、反映する必要がない理由を20字以内で述べよ。
模範解答
行:セットサービス注文明細の行
理由:セットサービスは実施対象ではないから
解説
解答の論理構成
- テーブル間の生成タイミング
- 注文確定 → “注文明細” に行作成
- 実施予定登録 → “実施明細” に行作成
- 実施対象のサービス種別
- “サービスには、個別サービス、セットサービス及びオプションサービスの3種類”
- “セットサービスとは、個別サービスを複数組み合わせたもの”
- 現場で行う作業
- “1回の実施には一つ又は複数のサービスが含まれ” とあるが、 個別に作業時間を割り当てる仕様は “個別サービス、オプションサービスごとに、予定作業時間数を割り当てる。”
- 逆に “セットサービス” に対して作業時間は割り当てない。
- よって “実施明細” を作る際、実際に清掃しない “セットサービス注文明細の行” は反映不要となり、理由は “セットサービスは実施対象ではないから” となる。
誤りやすいポイント
- “個別サービスを3件まとめたので作業時間を記録するだろう” と考え、セットサービスも実施対象に含めてしまう。
- 「選択した個別サービス」と「親セットサービス」の両方を二重登録して冗長なデータを生む。
- “オプションサービス” を忘れ、実施明細に含めないミス。
FAQ
Q: セットサービスが実施明細に無いと価格履歴が欠落しませんか?
A: “適用価格” は “注文明細” に残るため請求・分析は可能です。実施明細は作業実績専用と割り切ります。
A: “適用価格” は “注文明細” に残るため請求・分析は可能です。実施明細は作業実績専用と割り切ります。
Q: サービス区分を見れば判別できますか?
A: はい。“サービス区分” 列で “セット” を除外すれば実施明細に積み上げる対象を機械的に抽出できます。
A: はい。“サービス区分” 列で “セット” を除外すれば実施明細に積み上げる対象を機械的に抽出できます。
Q: 今後セットサービス単位で作業時間を管理したい場合は?
A: セットサービス自体に標準作業時間数を持たせ、新たに実施明細へ紐付ける列を追加すれば対応可能です。
A: セットサービス自体に標準作業時間数を持たせ、新たに実施明細へ紐付ける列を追加すれば対応可能です。
関連キーワード: サブタイプ構造、外部キー制約、正規化、業務要件分析
設問3:注文と実施の管理について(1)、(2)に答えよ。
問題文を見る(2)
〔継続注文の変更〕 に対応するために、次の方針でテーブルの構造を見直すことにした。
・新たなテーブルは追加せず、図2のテーブル構造を変更する。
・テーブル構造の変更は、変更対象のテーブルに対して、同じ役割の列を一つだけ追加する。
この方針で見直した場合の追加する列について、役割を表す適切な列名を答えよ。 また、変更すべきテーブル名を全て答え、それらのテーブルごとに、追加する列が主キーを構成する場合は主キー欄に “○”、外部キーを構成する場合は外部キー欄に“○” を記入して、次の表を完成させよ。
なお、表の欄は全て埋まるとは限らない。


模範解答
列名:注文変更年月日
テーブル:


解説
解答の導き方
列名:注文変更年月日
-
要件の抽出
問題文には「当初の注文確定時点の情報を含め、変更履歴を注文変更年月日ごとに保存する」とあり、変更履歴の識別単位が注文変更年月日であることが明確です。よって追加する列名は注文変更年月日とします。 -
方針の制約確認
問題文の方針に「新たなテーブルは追加せず、…同じ役割の列を一つだけ追加する」とあるので、同じ名前の列を必要な既存テーブルにだけ一つずつ追加する設計を採ります。 -
現行キー関係の確認(図2参照)
図2では注文の主キーが「注文番号」、注文明細の主キーが {注文番号, 注文明細番号}、実施の主キーが「実施番号」、実施明細の主キーが {実施番号, 実施明細番号} です。また注文明細は注文番号で注文を参照し、実施は注文番号で注文を、実施明細は {注文番号, 注文明細番号} で注文明細を参照しています。 -
変更履歴保存のために必要なキー設計の結論
- 注文テーブル:変更履歴を注文変更年月日ごとに保存するため、同一の注文番号に対して複数行を持てるようにする必要があります。したがって注文に注文変更年月日を追加し、主キーを複合キー(注文番号, 注文変更年月日)とします。表中では「主キー欄に○」と記します。
- 注文明細テーブル:注文明細は「当初の注文確定時点の情報を含め」て履歴を残す対象になります。注文のバージョンごとに注文明細の状態を保持するためには、{注文番号, 注文明細番号} だけでは重複を避けられません。したがって注文明細にも注文変更年月日を追加し、注文明細の主キーを {注文番号, 注文変更年月日, 注文明細番号} にします。さらに注文明細は特定の注文バージョンを参照する必要があるため、追加列は外部キーとしても機能します(主キー○かつ外部キー○)。
- 実施テーブル:実施は各回ごとに固有の実施番号で一意に識別されるため、主キーに注文変更年月日を加える必要はありません。ただし、どの注文バージョンに基づいてその実施が登録されたかを明確にするため、注文変更年月日を外部キーとして追加します(外部キー○、主キー空欄)。
- 実施明細テーブル:実施明細も {実施番号, 実施明細番号} で一意に識別されていますが、どの注文明細(=どの注文バージョン)に対応するかを明確にするため、注文変更年月日を外部キーとして追加します(外部キー○、主キー空欄)。
-
参照整合性の扱い(追補)
- 注文明細に追加した注文変更年月日は注文明細の外部キーとして 注文(注文番号, 注文変更年月日) を参照するように設定します。
- 実施は 注文(注文番号, 注文変更年月日) を参照する外部キーを持ちます。
- 実施明細は 実施(実施番号) と 注文明細(注文番号, 注文変更年月日, 注文明細番号) をそれぞれ参照する外部キーを持ちます。
最終的に表に記入する内容は以下のとおりです。
(最終行は空欄)
誤りやすいポイント
- 注文明細の主キー {注文番号, 注文明細番号} に注文変更年月日を加えることを忘れ、注文のバージョンごとの明細を保持できない設計にしてしまう点。
- 注文に注文変更年月日を追加しても、子テーブル(注文明細、実施、実施明細)に同列を追加しないと参照先が不明確になり、参照整合性が維持できなくなる点。必ず関連する子テーブルにも同名の列を追加して外部キーを拡張します。
- 実施/実施明細に対して不必要に主キーに変更を加えること。これらは実施番号/{実施番号, 実施明細番号} で一意に識別できるため、主キーを変えずに外部キーとして追加するだけで十分です。
FAQ
Q: 注文変更年月日を注文の主キーに含める理由は何ですか?
A: 問題文で「変更履歴を注文変更年月日ごとに保存する」と明示されているため、同一の注文番号で複数バージョン(初回や変更後)を保存できるように、識別キーに注文変更年月日を含めて複合主キーとする必要があります。これにより各バージョンを一意に特定できます。
A: 問題文で「変更履歴を注文変更年月日ごとに保存する」と明示されているため、同一の注文番号で複数バージョン(初回や変更後)を保存できるように、識別キーに注文変更年月日を含めて複合主キーとする必要があります。これにより各バージョンを一意に特定できます。
Q: 注文明細に注文変更年月日を主キーに含める必然性はありますか?
A: 注文明細の履歴(注文の各バージョンに対応する明細)を保持する要件があるため、同一の {注文番号, 注文明細番号} が複数バージョンで存在する可能性を許容するには注文変更年月日を含めた複合主キーにするのが単純で安全な方法です(注文明細番号を毎回新規採番する運用にすれば主キーに含めない選択肢もありますが、問題の方針の下では同一役割の列を追加する方が整合的です)。
A: 注文明細の履歴(注文の各バージョンに対応する明細)を保持する要件があるため、同一の {注文番号, 注文明細番号} が複数バージョンで存在する可能性を許容するには注文変更年月日を含めた複合主キーにするのが単純で安全な方法です(注文明細番号を毎回新規採番する運用にすれば主キーに含めない選択肢もありますが、問題の方針の下では同一役割の列を追加する方が整合的です)。
Q: 実施/実施明細はなぜ主キーを変更しないのですか?
A: 実施は実施番号、実施明細は {実施番号, 実施明細番号} で固有に識別されるため、主キーに変更を加える必要はなく、どの注文バージョンに紐づくかを示す外部キー(注文変更年月日を含む)だけを追加すれば参照先の特定が可能です。
A: 実施は実施番号、実施明細は {実施番号, 実施明細番号} で固有に識別されるため、主キーに変更を加える必要はなく、どの注文バージョンに紐づくかを示す外部キー(注文変更年月日を含む)だけを追加すれば参照先の特定が可能です。
関連キーワード: 履歴管理、バージョニング、複合主キー、参照整合性、正規化



