基本情報技術者 2019年 秋期 午後 問03
書籍及び貸出情報を管理する関係データベースの設計及び運用に関する次の記述を読んで、設問1〜3に答えよ。
D社の部署である資料室は、業務に関連する書籍を所蔵しており、従業員への貸出しを2015年4月から実施している。
所蔵する書籍を管理するデータベースは、書籍の情報を管理する書籍情報表と貸出状況を管理する貸出表とで構成されている。データベース構成を、図1に示す。下線付きの項目は主キーを表し、下破線付きの項目は外部キーを表す。各書籍は1冊しか所蔵していない。

〔貸出表に関する説明〕
(1) 従業員に書籍を貸し出す際は、一意の貸出番号、貸し出す書籍のISBNコード、従業員番号、貸出日及び返却予定日を設定し、返却日にはNULLを設定したレコードを追加する。
(2) 書籍が返却されたら、対象のレコードの返却日に返却された日付を設定する。
設問1:
問題文を見る 次のSQL文は、ISBNコードがISBN978-4-905318-63-7の書籍の貸出し状態を表示するSQL文である。ISBNコードで貸出表を検索し、最も新しい貸出日のレコードの返却日にNULLが設定されている場合は、“貸出中”が表示される。また、最も新しい貸出日のレコードの返却日に日付が設定されている場合、及び貸出実績のない書籍の場合は、“貸出可”が表示される。に入れる正しい答えを、解答群の中から選べ。ここで、検索に使用するISBNコードの書籍は必ず所蔵されているものとする。また、返却された書籍はその日のうちに再び貸し出されることはない。
SELECT 貸出表.ISBNコード,
CASE WHEN a
END AS 書籍状態
FROM 貸出表
WHERE 貸出表.ISBNコード = 'ISBN978-4-905318-63-7'
AND 貸出表.貸出日 = (SELECT b FROM 貸出表
WHERE 貸出表.ISBNコード = 'ISBN978-4-905318-63-7')
UNION ALL
SELECT DISTINCT 書籍情報表.ISBNコード, '貸出可' AS 書籍状態
FROM 書籍情報表
WHERE 書籍情報表.ISBNコード = 'ISBN978-4-905318-63-7'
AND NOT EXISTS (SELECT 貸出表.ISBNコード FROM 貸出表
WHERE 貸出表.ISBNコード = 'ISBN978-4-905318-63-7')
aに関する解答群
ア:貸出表.返却日 IS NOT NULL THEN '貸出中' ELSE '貸出可'
イ:貸出表.返却日 IS NOT NULL THEN '貸出中' WHEN 貸出表.返却日 IS NULL THEN '貸出可'
ウ:貸出表.返却日 IS NULL THEN '貸出可' ELSE '貸出中'
エ:貸出表.返却日 IS NULL THEN '貸出中' WHEN 貸出表.返却日 IS NOT NULL THEN '貸出可'
bに関する解答群
ア:DISTINCT 貸出表.貸出日
イ:MAX(貸出表.貸出日)
ウ:MIN(貸出表.貸出日)
エ:貸出表.貸出日
模範解答
a:エ、b:イ
解説
解答の導き方
このSQLは、ISBN(International Standard Book Number:書籍を識別する番号)コードで貸出履歴を調べ、最も新しい貸出の状態を表示します。貸出履歴がない場合は、別の処理で「貸出可」と表示します。
-
最も新しい貸出日を選びます。
SQL(Structured Query Language:データベースを操作する言語)では、MAX関数を使うと、指定した値の中から最大の値を取り出せます。日付の場合、最大の値は最も新しい日付です。したがって、bにはMAX(貸出表.貸出日)が入ります。外側の検索では、その結果と貸出日が一致するレコードを探すので、最も新しい貸出日のレコードを選べます。よって、bはイです。MIN(貸出表.貸出日)では最も古い日付になります。また、貸出日をそのまま指定しても、貸出履歴が複数あると最も新しい日付に絞れません。 -
最新の貸出が返却済みかを判定します。
貸出表に関する説明では、貸出時に「返却日にはNULLを設定」し、返却されたら返却日を設定するとあります。つまり、返却日がNULLなら貸出中で、日付が設定されていれば返却済みです。CASE式は、条件に応じて表示する値を切り替える書き方です。返却日がNULLなら「貸出中」、NULLでなければ「貸出可」と表示するので、aには次の条件が入ります。貸出表.返却日 IS NULL THEN '貸出中' WHEN 貸出表.返却日 IS NOT NULL THEN '貸出可'これは選択肢のエです。NULLは値が設定されていない状態を表すため、NULLかどうかの判定にはIS NULLまたはIS NOT NULLを使います。 -
貸出履歴がない場合も「貸出可」と表示します。
SQLの後半では、NOT EXISTSによって、そのISBNコードの貸出履歴がないことを確認します。履歴がなければ、書籍情報表から「貸出可」を表示します。貸出履歴がないとき、最初の検索では最も新しい貸出日のレコードが見つかりません。一方、後半の検索は貸出履歴がない条件を満たすため、「貸出可」を表示できます。貸出履歴がある場合は、最初の検索で最新の貸出状態が表示されます。
誤りやすいポイント
-
NULLを返却済みと取り違えないことです。
貸出時に返却日へNULLを設定するため、NULLは「まだ返却されていない」状態を表します。 -
MAX関数とMIN関数を取り違えないことです。
最も新しい日付を求めるにはMAX関数を使います。MIN関数で得られるのは最も古い日付です。 -
貸出履歴がない場合の処理を見落とさないことです。
貸出履歴がある場合の検索だけでは、履歴のない書籍の状態は表示できません。そのため、後半の検索で貸出履歴がない書籍に「貸出可」を表示しています。
FAQ
Q: 返却日の判定で、返却日 = NULLとは書けないのですか?
A: NULLは通常の値とは異なるため、等号ではなくIS NULLまたはIS NOT NULLを使って判定します。
A: NULLは通常の値とは異なるため、等号ではなくIS NULLまたはIS NOT NULLを使って判定します。
Q: 貸出履歴がある場合も、後半の検索で「貸出可」と表示されませんか?
A: 後半の検索にはNOT EXISTSの条件があります。貸出履歴がある場合はその条件を満たさないため、後半の検索結果には含まれません。
A: 後半の検索にはNOT EXISTSの条件があります。貸出履歴がある場合はその条件を満たさないため、後半の検索結果には含まれません。
Q: なぜ最も新しい貸出日の返却日を確認するのですか?
A: 過去の貸出が返却済みでも、その後に新しい貸出があれば現在は貸出中かもしれません。最も新しい貸出の返却日を確認することで、現在の状態を判断できます。
A: 過去の貸出が返却済みでも、その後に新しい貸出があれば現在は貸出中かもしれません。最も新しい貸出の返却日を確認することで、現在の状態を判断できます。
関連キーワード: SQL、CASE式、NULL値、集約関数、サブクエリ、UNION ALL
設問2:
問題文を見る 2018年4月1日から2019年3月31日までの間に4回以上貸し出した書籍の一覧を取得することにした。次のSQL文のに入れる正しい答えを、解答群の中から選べ。
SELECT 書籍情報表.ISBNコード, 書籍情報表.書籍名, COUNT(*) AS 貸出回数
FROM 書籍情報表, 貸出表
WHERE 書籍情報表.ISBNコード = 貸出表.ISBNコード c
cに関する解答群
ア:AND (貸出表.貸出日 >= '2018-04-01' OR 貸出表.貸出日 <= '2019-03-31')
GROUP BY 書籍情報表.ISBNコード, 書籍情報表.書籍名
HAVING COUNT(*) >= 4
イ:AND 貸出表.貸出日 BETWEEN '2018-04-01' AND '2019-03-31'
GROUP BY 書籍情報表.ISBNコード, 書籍情報表.書籍名
HAVING COUNT(*) >= 4
ウ:AND 貸出表.貸出日 >= '2018-04-01' AND 貸出表.貸出日 <= '2019-03-31'
AND COUNT(*) >= 4
エ:GROUP BY 書籍情報表.ISBNコード, 書籍情報表.書籍名, 貸出表.貸出日
HAVING 貸出表.貸出日 >= '2018-04-01' AND 貸出表.貸出日 <= '2019-03-31'
AND COUNT(*) >= 4
模範解答
c:イ
解説
解答の導き方
この設問は、「2018年4月1日から2019年3月31日までの間」に、書籍ごとの貸出回数を数え、その回数が4回以上の書籍を取り出すSQL(Structured Query Language:関係データベースを検索・操作するための言語)を完成させる問題です。
-
書籍情報と貸出情報を対応させます。
SQLでは、FROM句に書かれた表を使って検索します。WHERE句にある「書籍情報表.ISBNコード = 貸出表.ISBNコード」は、ISBNコードが同じ書籍情報と貸出情報を対応させる条件です。これにより、どの書籍の貸出記録かを特定できます。 -
貸出日が指定期間内の記録だけを残します。
期間の初日以降であり、かつ最終日以前であることが必要です。つまり、貸出日は次の両方の条件を満たさなければなりません。貸出表.貸出日 >= '2018-04-01' 貸出表.貸出日 <= '2019-03-31'SQLのBETWEENは、指定した範囲の両端を含む条件です。そのため、期間の両端を含める次の条件でも同じ意味になります。AND 貸出表.貸出日 BETWEEN '2018-04-01' AND '2019-03-31' -
書籍ごとに貸出記録をまとめます。
GROUP BYは、指定した項目の値が同じ行をひとまとめにする句です。書籍ごとに貸出回数を数えるため、ISBNコードと書籍名でグループ化します。GROUP BY 書籍情報表.ISBNコード, 書籍情報表.書籍名そのグループ内の行数をCOUNT(*)で数えれば、その書籍の期間内の貸出回数になります。 -
貸出回数が4回以上のグループだけを残します。
HAVINGは、GROUP BYでまとめた後のグループに条件を付ける句です。したがって、COUNT(*)が4以上であることはHAVINGで指定します。HAVING COUNT(*) >= 4
このように、期間の条件をWHEREに置き、書籍ごとに集計してからHAVINGで回数を絞り込むので、cにはイが入ります。
誤りやすいポイント
-
選択肢アのORに注意します。
指定期間に入るには、貸出日が初日以降であることと、最終日以前であることの両方が必要です。ORにすると、どちらか一方を満たすだけで対象になります。例えば、期間より前の日付は「最終日以前」を満たし、期間より後の日付は「初日以降」を満たしてしまいます。 -
集計条件をWHEREに置かないようにします。
WHEREは、集計する前の個々の行を絞り込むための句です。一方、「4回以上」のように集計後の回数を条件にする場合は、HAVINGを使います。 -
貸出日をGROUP BYに加えないようにします。
貸出日もグループ化すると、書籍ごとではなく、書籍と貸出日の組合せごとに回数を数えることになります。期間全体の貸出回数を調べるには、貸出日でグループを分けず、WHEREで期間を絞り込みます。
FAQ
Q: BETWEENの範囲には、初日と最終日も含まれますか?
A: はい。BETWEENは範囲の両端を含みます。この設問では、'2018-04-01'と'2019-03-31'の貸出記録も対象です。
A: はい。BETWEENは範囲の両端を含みます。この設問では、'2018-04-01'と'2019-03-31'の貸出記録も対象です。
Q: COUNT(*)は何を数えていますか?
A: GROUP BYでまとめた書籍ごとに、該当する貸出表の行数を数えています。貸出表には貸出ごとにレコードを追加するため、行数が貸出回数になります。
A: GROUP BYでまとめた書籍ごとに、該当する貸出表の行数を数えています。貸出表には貸出ごとにレコードを追加するため、行数が貸出回数になります。
Q: 返却日がNULLの貸出記録も数えますか?
A: はい。このSQLの条件には返却日の指定がありません。貸出日が指定期間内であれば、返却済みかどうかにかかわらず貸出回数に含まれます。
A: はい。このSQLの条件には返却日の指定がありません。貸出日が指定期間内であれば、返却済みかどうかにかかわらず貸出回数に含まれます。
関連キーワード: SQL、GROUP BY、HAVING、BETWEEN、集計関数
設問3:
問題文を見る 従業員と資料室担当者の利便性を向上させる目的で、所蔵する書籍を管理するデータベースを再構築することにした。
データベースの再構築に当たり、従業員と資料室担当者から要望が出された。次の記述中のに入れる適切な答えを、解答群の中から選べ。
〔従業員と資料室担当者からの要望〕
要望1 ISBNコードが同じ書籍を複数冊所蔵できるようにしたい。
要望2 書籍の購入日を管理できるようにしたい。
要望3 ISBNコードごとに所蔵する書籍数及び貸出し中の書籍数(以下、貸出中件数という)が分かるようにしたい。
要望4 ISBNコードが同じ書籍は同じラックに保管して、書籍が収納されているラックが分かるようにしたい。
従業員と資料室担当者からの要望を反映したデータベース構成案を、図2に示す。下線付きの項目は主キーを表し、下破線付きの項目は外部キーを表す。
〔要望に対するデータベース修正内容〕
修正1 要望1に対応するために書籍表を追加して、資料室で所蔵している各書籍に一意の書籍番号を割り振って、それを主キーとした。また、貸出表のISBNコードを書籍番号に変更した。
修正2 要望2に対応するために書籍表に購入日を設けた。
修正3 要望3に対応するために書籍管理ビューを追加した。
修正4 要望4に対応するためにラック表を追加して、書籍情報表に外部キーとしてラック番号を追加した。 要望を反映したデータベース構成案では、既に所蔵している書籍とISBNコードが同じ書籍を追加購入した場合に、レコードを追加する必要のある表はdである。
また、需要がなくなった書籍を廃棄する場合は、ISBNコードが同じ書籍を全て廃棄する。データベースに対して行う操作は、次の①〜④を、eの順序で行う必要がある。
① 書籍情報表の主キーが対象ISBNコードのレコードを削除する。
② 書籍表から対象ISBNコードに対応する書籍番号を抽出する。
③ 書籍表の対象ISBNコードに対応するレコードを削除する。
④ 貸出表の対象書籍番号に対応するレコードを削除する。
dに関する解答群
ア:書籍表
イ:書籍表及びラック表
ウ:書籍情報表及び書籍表
エ:書籍情報表、書籍表及びラック表
eに関する解答群
ア:②→①→③→④
イ:②→①→④→③
ウ:②→③→①→④
エ:②→③→④→①
オ:②→④→①→③
カ:②→④→③→①
模範解答
d:ア、e:カ
解説
解答の導き方
図2では、書籍の情報を「書籍情報表」、所蔵している1冊ずつの情報を「書籍表」、貸出状況を「貸出表」で管理しています。
主キー(表の中で1行を特定する項目)は、図で下線が付いた項目です。外部キー(別の表の行を参照して、表同士を結び付ける項目)は、下破線が付いた項目です。
d:追加購入した書籍を登録する表
要望1には「ISBNコードが同じ書籍を複数冊所蔵できるようにしたい」とあります。ISBNコードは同じ書籍をまとめるための番号ですが、書籍表の書籍番号は、所蔵している1冊ずつを区別するための番号です。
そのため、同じISBNコードの書籍を追加購入したときは、新しい書籍番号を付けて、購入日とともに書籍表に登録します。書籍情報表にはそのISBNコードの情報がすでにあり、要望4では同じISBNコードの書籍を同じラックに保管するため、ラック表にも新しい行を追加する必要はありません。
書籍管理ビューは、書籍表などの情報をもとに所蔵数や貸出中件数を示すビュー(表のデータを目的に合わせて見せる仕組み)です。追加した書籍は、書籍表に登録することで集計に反映されます。
したがって、レコード(表の1行分のデータ)を追加する表は「書籍表」です。答えはアです。
e:書籍を廃棄するときの操作順序
書籍表のISBNコードは、書籍情報表のISBNコードを参照する外部キーです。また、貸出表の書籍番号は、書籍表の書籍番号を参照する外部キーです。
このような参照関係では、参照されている行を先に削除すると、参照先がなくなる問題が起きます。参照先が存在しない状態を防ぐルールを、参照整合性といいます。そこで、貸出表から書籍表、書籍情報表の順に削除します。
- まず②で、対象ISBNコードに対応する書籍番号を調べます。ISBNコードが同じ書籍を複数冊所蔵している場合があるため、該当する書籍番号を先に確認します。
- 次に④で、その書籍番号を参照している貸出表のレコードを削除します。貸出表のレコードが残っていると、書籍表の書籍番号を削除できません。
- 続いて③で、書籍表から対象ISBNコードに対応するレコードを削除します。
- 最後に①で、書籍表から参照されなくなったISBNコードを、書籍情報表から削除します。
よって、操作順序は②→④→③→①で、答えはカです。
誤りやすいポイント
- ISBNコードと書籍番号を同じものとして考えないようにします。ISBNコードは同じ書籍をまとめる番号で、書籍番号は所蔵している1冊ずつを区別する番号です。
- 追加購入時に、書籍情報表にも行を追加すると考えないようにします。同じISBNコードの書籍情報はすでに登録されているため、追加するのは書籍表の行です。
- 削除では、参照している側の表から先に消します。貸出表が書籍表を参照し、書籍表が書籍情報表を参照しているため、貸出表、書籍表、書籍情報表の順に削除します。
- 対象ISBNコードの行を先に削除すると、書籍表から書籍番号を調べられなくなります。そのため、②は最初に行います。
FAQ
Q: なぜ②で書籍番号を先に調べるのですか?
A: 貸出表が参照しているのはISBNコードではなく書籍番号です。対象ISBNコードに対応する書籍番号を先に調べておかないと、貸出表から削除すべきレコードを特定できません。
A: 貸出表が参照しているのはISBNコードではなく書籍番号です。対象ISBNコードに対応する書籍番号を先に調べておかないと、貸出表から削除すべきレコードを特定できません。
Q: 貸出表のレコードを、書籍表のレコードより先に削除するのはなぜですか?
A: 貸出表の書籍番号は、書籍表の書籍番号を参照しているからです。貸出表のレコードが残ったまま書籍表のレコードを削除すると、参照先がなくなってしまいます。
A: 貸出表の書籍番号は、書籍表の書籍番号を参照しているからです。貸出表のレコードが残ったまま書籍表のレコードを削除すると、参照先がなくなってしまいます。
Q: 書籍を廃棄するとき、ラック表のレコードも削除しますか?
A: この設問の操作では削除しません。ラック表はラック自体の情報を管理する表であり、特定の書籍を廃棄する操作とは別だからです。
A: この設問の操作では削除しません。ラック表はラック自体の情報を管理する表であり、特定の書籍を廃棄する操作とは別だからです。
関連キーワード: 主キー、外部キー、参照整合性、ビュー、データベース設計



