ITパスポート 2018年 春期 問81
問題文
顧客名と住所、商品名と単価、顧客が注文した商品の個数と注文した日付を関係データベースで管理したい。正規化された表として、適切なものはどれか。ここで、下線は主キーを表し、顧客名や商品名には、それぞれ同一のものがあるとする。

選択肢
ア:(正解)
イ:
ウ:
エ:
🔒 解説は解答すると表示されます
題目:顧客名と住所、商品名と単価、顧客が注文した商品の個数と注文した日付を関係データベースで管理したい【ITパスポート 解説】
正解の理由
選択肢 ア は、顧客(customer)、商品(product)、注文(order)を別々の表に分けています。これは正規化(normalization:データの重複を減らし更新や削除の不整合を防ぐ設計ルール)に従った設計です。
- 顧客番号は顧客表の主キー(primary key:各レコードを一意に識別する列)になっています。これにより、顧客名や住所を一箇所にだけ持てます。
- 商品番号は商品表の主キーで、商品名や単価を商品表で一元管理します。
- 注文表は、注文番号(主キー)に顧客番号と商品番号(それぞれ外部キー:foreign keyで他表の主キーを参照する列)を持ち、個数と日付を記録します。
この構成だと、同じ顧客名や商品名が複数回現れても、名前そのものを注文表に繰り返し書かずに済み、データの冗長性(重複)と更新ミスを防げます。以上の点から ア が適切です。
解法ステップ
- 要求されている情報を分けて考える
- 顧客に関する情報(顧客名、住所)
- 商品に関する情報(商品名、単価)
- 注文に関する情報(誰が何を何個、いつ注文したか)
- 「同じ情報が繰り返されないように」表を分ける(=正規化)
- 顧客は顧客表、商品は商品表、注文は注文表に分ける。
- 主キー(各表でレコードを一意に識別する列)を決める
- 顧客表:顧客番号、商品表:商品番号、注文表:注文番号(場合によっては明細テーブルの複合キー)
- 注文表には参照として顧客番号と商品番号を持たせる(名前や単価を直接書かない)
- 要件によっては「注文ヘッダ」と「注文明細」に分ける(注文が複数商品を含む可能性があるとき)
選択肢別の誤答解説
-
ア(正解)
顧客/商品/注文が分離されており、顧客番号・商品番号・注文番号を主キーにしている。重複を防ぎ、更新や削除の不整合を避けられる設計です。 -
イ(誤り)
注文表に「顧客名」「商品名」を直接入れています。名前は重複する可能性があり、同じ顧客名を持つ複数顧客の区別ができない・名前変更時に複数行を更新しなければならない等の問題が生じます。したがって正規化の観点で不適切です。 -
ウ(誤り)
顧客表に「日付」が入っています。日付は「いつ注文したか」に関する情報であり、顧客固有の属性ではありません(顧客が持つ属性は住所や連絡先)。また商品表が示されておらず、注文表に「単価」を入れているため、同じ商品で単価が変わると整合性が困難になります。設計が責務に応じて分かれていません。 -
エ(誤り)
商品表に「個数」が入っている点が不適切です。個数は注文ごとに変わる値であり、商品そのものの属性ではありません(商品は「単価」や「商品名」などが属性)。さらに顧客の独立した表がなく、注文表に顧客名や住所を直接持たせているため冗長と更新ミスの原因になります。
よくある誤解
-
「名前や住所をそのまま使えば分かりやすい」は正しくない
- 名前や住所は重複や変更が起きやすく、識別子(キー)としては不安定です。代わりに番号(顧客番号・商品番号)を使うのが基本です。
-
「注文に単価を入れないと計算できない」は誤解
- 注文時の単価を保存したい場合は、注文の明細(注文明細)に「注文時点の単価」を持たせるのが正しい設計です。商品表の単価は最新の価格で、過去の注文の価格とは異なる場合があります。
-
「1つの表に全部まとめれば簡単」は危険
- 一見簡単でも、データの重複や更新時の不整合(更新異常)が発生しやすくなります。長期運用や集計を考えると表を分ける方が安全です。
補足コラム
-
正規化の段階について(かんたんに)
- 1NF(第1正規形):すべての列が原子値(分割できない値)であること。
- 2NF(第2正規形):1NFかつ部分関数従属がないこと(複合キーを使う場合の話)。
- 3NF(第3正規形):2NFかつ推移的依存がないこと(A→B→C のような余計な関連がない)。
選択肢 ア は顧客・商品・注文を分離しており、実務で求められる基本的な正規化(3NFに近い状態)になっています。
-
実務的な注意点(注文に複数商品がある場合)
多くの注文は複数商品を含みます。このときは「注文ヘッダ」表(注文番号、顧客番号、注文日など)と「注文明細」表(注文明細ID、注文番号、商品番号、個数、注文時単価など)に分けるのが一般的です。今回の選択肢は簡略化されていますが、考え方は同じです。 -
例:簡単なCREATE文(イメージ)
CREATE TABLE 顧客 ( 顧客番号 INTEGER PRIMARY KEY, 顧客名 VARCHAR(100), 住所 VARCHAR(200) ); CREATE TABLE 商品 ( 商品番号 INTEGER PRIMARY KEY, 商品名 VARCHAR(100), 単価 DECIMAL(10,2) ); CREATE TABLE 注文 ( 注文番号 INTEGER PRIMARY KEY, 顧客番号 INTEGER, 商品番号 INTEGER, 個数 INTEGER, 日付 DATE, FOREIGN KEY (顧客番号) REFERENCES 顧客(顧客番号), FOREIGN KEY (商品番号) REFERENCES 商品(商品番号) );(SQLは構造を示す例です。実際は注文明細テーブルに分けるなど拡張する場合が多いです。)
FAQ
Q1: 注文に複数の商品がある場合はどうする?
A1: 注文ヘッダ(注文番号・顧客番号・日付)と注文明細(注文番号+商品番号で各商品の個数や注文時単価を記録)に分けます。こうすると1つの注文で複数行を表現できます。
A1: 注文ヘッダ(注文番号・顧客番号・日付)と注文明細(注文番号+商品番号で各商品の個数や注文時単価を記録)に分けます。こうすると1つの注文で複数行を表現できます。
Q2: 商品の単価が変わったとき、過去の注文の金額はどうなる?
A2: 過去の注文は注文時点の単価を注文明細に保存しておくのが安全です。商品表の単価は最新価格を表します。
A2: 過去の注文は注文時点の単価を注文明細に保存しておくのが安全です。商品表の単価は最新価格を表します。
Q3: 名前を主キーに使えますか?
A3: 推奨されません。名前は重複したり変更されたりするため、安定した一意の識別子(番号)を主キーにするのが一般的です。
A3: 推奨されません。名前は重複したり変更されたりするため、安定した一意の識別子(番号)を主キーにするのが一般的です。
関連キーワード: 正規化、主キー、外部キー、リレーショナルデータベース、顧客管理、商品管理、注文管理、注文明細、第3正規形

\ せっかくなら /
ITパスポートを
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

