【応用情報】午後『データベース』のリレーションを制する!第3回『本文を読んで判断』編
はじめに
今回は、応用情報技術者試験の午後『問6:データベース』 に出題されることが多い(ほぼ毎回)リレーションを回答する際のポイントについて書きます。
この記事は続編(3回目) となっております。
まずは前回までの記事を読んで頂くことで、何をやろうとしているのかが分かると思います。
今回のサンプル
前回までとは違う過去問を使い、解説をします。
※出典:令和6年度 秋期 応用情報技術者試験 午後 問題冊子
ER図だけでは見抜けないパターン
前回まででご紹介したテクニックでは正解が導けないパターンです。
もっとも、試験的にはこれが本来の解き方です(※決して前回までが邪道ということではありません)
予想してみよう
では、空欄『b』には何が入るのか?
- ー(1対1):可能性あり
- →(1対多):可能性あり
- ←(多対1):可能性なし
- ←→(多対1):可能性なし
まず、4番はそもそも実装できないので違います(※第1回の記事を参照)
そして、3番も違います。理由はこのような関係だからです。
お互いのテーブルの項目を見ると 『取引ID』で繋がることが予想できます。
(空欄『c』によって変わる場合もあるが、位置的に可能性は低い。※詳細は割愛します)
その際、外部キー側が矢印の先端(多)となるので、3番も違うということです。
あとは?
ここまでで2択に絞れました。
しかし、ここから先は問題文から要件や仕様を判断する必要があります。
問題文を読むと
業務要件が書いてあります。
これを設計(つまりER図) に落とし込むわけです。
字がギッチリしてて「うわ~」って思うかもしれないですが、キーワードで探すような読み方をすれば全部を読まなくても、欲しい情報が見つかります。
上記①②③は、このようなやりとりになると考えられます。
- ①:取引した際に「何回かに分けて送ってくれます?」
- ②:何度か続けて取引して「まとめて送ってくれます?」
- ③:「いや、どっちもできませんよ。うちは1取引1発送ですから!」
「1取引1発送」つまり、正解は1番の『ー(1対1)』です。
実際のデータをイメージしてみよう
実際にテーブル定義を作ってみましょう。
項目は、検証に最低限必要なものだけに絞ります。
テーブル『取引』
取引ID(主キー) | 出品ID | 購入者ID(今回は『購入者氏名』とする) |
---|---|---|
1001 | 1 | 鈴木 |
1002 | 2 | 佐藤 |
1003 | 2 | 佐藤 |
1004 | 3 | 田中 |
1005 | 3 | 田中 |
1006 | 3 | 田中 |
テーブル『発送』
発送ID(主キー) | 取引ID | 配送方法ID(今回は『配送方法名称』とする) |
---|---|---|
HA07 | 1001 | 郵送 |
HA08 | 1002 | 郵送 |
HA09 | 1003 | 宅配便 |
HA10 | 1004 | 宅配便 |
HA11 | 1005 | 郵送 |
まず、テーブル同士でリレーション(結合)できる項目は『取引ID』です。
業務要件に合わせた仕様だと、テーブル『発送』の『取引ID』は重複が許されません。
主キーではないのに、どうやって制御するのか?
それはこの後のSQLを書くところをご覧ください。
ちなみに、テーブル『発送』の方は1レコード足りません。
「取引ID'1006'が、まだ発送されていないから」という状況を表現してみました。
今回はゼロ表記については特に指定がないので、こういうデータは問題ありません。
※ゼロ表記については前回の記事を参照してください。
SQLを書いて動かしてみよう
では、今回も実際にSQLを書いて実際に結合する様子を見てみましょう。
正直、この連載で一番やりたいことはコレです(笑)
PostgreSQLで書きますので、よろしければ試してみてください。
※簡単に試す方法はこちらの記事を参考にして下さい。
まず、先程のデータを作ります。
テーブル『取引』の取引IDにUNIQUE制約(一意制約) を付与しているのがポイントです。
これにより、主キー以外でも重複させないようにすることができます。
-- 取引テーブルを作る
CREATE TABLE 取引 (
取引ID INTEGER PRIMARY KEY -- 主キー
, 出品ID INTEGER
, 購入者氏名 VARCHAR
);
-- 取引テーブルにデータを登録
INSERT INTO 取引 VALUES
(1001 ,1 ,'鈴木')
,(1002 ,2 ,'佐藤')
,(1003 ,2 ,'佐藤')
,(1004 ,3 ,'田中')
,(1005 ,3 ,'田中')
,(1006 ,3 ,'田中');
-- 発送テーブルを作る
CREATE TABLE 発送 (
発送ID CHAR(4) PRIMARY KEY -- 主キー
, 取引ID INTEGER UNIQUE -- 一意制約(この項目の重複を許さない)
, 配送方法名称 VARCHAR
);
-- 発送テーブルにデータを登録
INSERT INTO 発送 VALUES
('HA07' ,1001 ,'郵送')
,('HA08' ,1002 ,'郵送')
,('HA09' ,1003 ,'宅配便')
,('HA10' ,1004 ,'宅配便')
,('HA11' ,1005 ,'郵送');
では、リレーションを張って両方のテーブルからデータを取得するSELECT文を発行します。
例として『取引ごとに、誰に、どうやって届けるのか?』という要件に応えるとします。
-- 取引ごとの購入者と配送方法を取得
SELECT
取引ID
,th.購入者氏名
,ha.配送方法名称
FROM 取引 th
-- 内部結合:配送方法が決定している取引のみ取得
INNER JOIN 発送 ha USING(取引ID)
ORDER BY 取引ID;
実行すると、このような結果になります。
どの取引で、誰にどうやって送るかが分かります。
注意点
結局、今回のサンプルではUNIQUE制約が無くても結果は同じになります。
ただし制約が無い場合、やろうと思えば分割発送が可能になります。
1回の発送に対して、複数の取引を登録できますからね。
このあたりは、業務要件次第で制約を付けるか否か判断します。
さいごに
いかがでしたか?
私としては、今回が一番「試験問題を解いている感じがする!」と思います。
同時に、実務で役立てるための本質も少しお伝えできた気がします。
そして、3回もやっておいてまだ続きがあります(笑)
本題は終わったつもりなので、補足事項を解説する予定です。
また懲りずに付いてきていただけると嬉しいです^^;
では、今回は以上です。
ここまでお付き合い頂き、ありがとうございましたm(_ _)m
Discussion