応用情報技術者 2017年 春期 午後 問06
稟議申請システムに関する次の記述を読んで、設問1~4に答えよ。
S社では、機器の購入や他社との契約の金額が10万円を超える場合には、承認権をもつ者による承認が必要である。承認を得る際、担当者は決まった書式に従って稟議申請書を作成し、稟議申請をする。
稟議申請には、大きく分けて購買稟議と契約稟議がある。購買稟議の場合は、申請者の所属部署の部長、購買部の担当者、購買部の部長の順で、承認が必要となる。また、契約稟議の場合は、申請者の直属の上司、所属部門の部長の順で、承認が必要となる。稟議申請書の書式は、購買稟議と契約稟議とで異なり、書式の種類は今後増える可能性がある。ただし、申請者自身が承認者に含まれるような稟議申請は行えない。
S社では、これまで紙の帳票で稟議申請を行っていたが、社内業務を効率化するために、稟議申請システムを開発して、Webシステム上で稟議申請を行うことにした。
〔稟議申請システムの概要〕
稟議申請システムには、ログイン画面、作成画面、一覧画面及び詳細画面の四つの画面がある。
ログイン画面では、利用者がユーザIDとパスワードを入力し、ログインする。
作成画面では、申請者が稟議申請に必要な事項を入力し、申請する。
一覧画面では、現在申請されている稟議申請を一覧の形式で見ることができる。
稟議申請の一覧には、自分が申請した稟議申請と、自分が承認者に含まれている稟議申請が表示される。一覧から稟議申請を選択すると詳細画面が表示される。
詳細画面では、稟議申請の内容と現在の承認の状態を確認できる。承認者が詳細画面で参照すると、稟議申請の内容のほかに承認入力欄が表示され、承認又は否認の入力を行うことができる。
〔作成画面〕
稟議申請は、書式ごとに必要な入力項目が一部異なる。申請者は、あらかじめ書式を選択してから内容を入力する。作成画面のレイアウトを図1に示す。
申請者は、稟議申請の内容を入力した後、申請を行う。承認の申請先は定義に従ってシステムが自動で設定するので、申請者が指定する必要はない。

稟議申請の入力項目は申請書項目と呼ばれ、書式ごとに項目を一意に識別する項目キーと、項目値の組合せで管理される。項目の定義を表1に示す。

〔詳細画面〕
詳細画面では、図1の内容が編集不可の状態で表示される。また、現在ログイン中の利用者に承認順が回ってきている稟議申請の場合は、画面に承認コメントの入力欄と、承認・否認のボタンが表示される。
承認者は、稟議申請の内容を確認し検討した上で、必要に応じてコメントを入力し、承認又は否認のボタンを押す。稟議申請は、承認者全員が承認すると可決となり、承認者のうち1人が否認した時点で否決となる。稟議申請が否決された場合、申請者は内容を修正して再度申請するか、申請を取りやめるかを判断する。
〔データベースの設計〕
購買申請システムのデータベースの設計を行った。設計したデータベースのE-R図を図2に、エンティティの概要を表2に示す。


例えば図1の購買要求申請の金額欄の場合、申請書項目マスタには、項目キーが'amount'、項目名が'金額'、項目値の型が'整数'のタプルが、申請書項目には、項目キーが'amount'、項目値が'2500000'のタプルが登録される。
このデータベースでは、E-R図のエンティティ名を表名にし、属性名を列名にして、適切なデータ型で表定義した関係データベースによって、データを管理する。
〔一覧画面〕
稟議申請の一覧画面には、申請書ID、タイトル、申請日、申請者のユーザID及び所属部署名を表示する。画面に表示する情報を検索するSQL文を図3に示す。ログイン中の利用者のユーザIDは、埋込変数':ユーザID'に設定されている。

また、経理部からの要望で、可決された稟議申請について、金額と支払日の一覧を出力できる機能を追加することになった。ただし、契約稟議については初回支払額だけ出力されればよい。金額と支払日の一覧を検索するSQL文を図4に示す。購買稟議申請の書式IDは'購買'、契約稟議申請の書式IDは'契約'である。

〔組織の改廃〕
運用開始後、利用者の部署異動や部署名の変更が行われることが想定されるが、システムの画面上で過去の稟議書を参照した際には、申請時の情報が表示される必要がある。しかし、図2の設計では①この要件を満たせない部分があるので、あるエンティティに属性を追加すると同時に図3のSQL文も修正することにした。
設問1:
図2のE-R図中のa、bに入れる適切なエンティティ間の関連及び属性名を答え、E-R図を完成させよ。ここで、エンティティ間の関連及び属性名の表記は図2の凡例に倣うこと。
模範解答
a:→
b:書式ID
解説
解答の論理構成
-
【問題文】には
“申請書 → 承認申請(1対多)a”
とあり、a は 申請書 から 承認申請 への 1 対多の関連そのものを示す記号です。E-R 図の凡例では、1 から多への関連は “→” で表記するため、a には “→” が入ります。 -
“稟議申請の承認申請状態を格納する” と記載されている承認申請は、否決後に “申請者は内容を修正して再度申請する” ことができるので、1 件の 申請書 に対して複数の 承認申請 が紐付く構造(1 対多)になります。
-
【問題文】の E-R 図補足には
“書式マスタ → 申請書(1対多)”
とあり、申請書 が どの書式で入力されたものかを識別する主キーは 書式マスタ 側の “書式ID” です。よって、申請書 には外部キー “書式ID” が必須となり、b には “書式ID” が入ります。 -
さらに本文では
“購買稟議申請の書式IDは'購買'、契約稟議申請の書式IDは'契約'である。”
と明示しており、属性名が “書式ID” であることを裏付けています。
以上より、a=“→”、b=“書式ID” が妥当となります。
誤りやすいポイント
- “1 件の稟議申請に 1 回しか承認プロセスが無い” と早合点し、a を “----”(1 対 1)や “←” としてしまう。否決後に再申請できるため 1 対多です。
- 外部キーを “書式名” と勘違いするケース。マスタを参照する際は数値または文字列でも ID を持つのが基本です。
- 図の凡例を確認せず、矢印方向を逆に書いて減点される。
FAQ
Q: なぜ “承認申請” を独立したエンティティに分けるのですか?
A: “否決 → 修正 → 再申請” のたびに履歴を残す必要があるためです。申請書を更新してしまうと過去のワークフローが追えなくなるので、承認申請を別エンティティで時系列保存します。
A: “否決 → 修正 → 再申請” のたびに履歴を残す必要があるためです。申請書を更新してしまうと過去のワークフローが追えなくなるので、承認申請を別エンティティで時系列保存します。
Q: “書式ID” が申請書にあるなら、申請書項目マスタとのリンクはどうなりますか?
A: 書式マスタ → 申請書 は 1 対多、書式マスタ → 申請書項目マスタ も 1 対多です。これにより、申請書がどの項目集合を使うかを “書式ID” ひとつで決定できます。
A: 書式マスタ → 申請書 は 1 対多、書式マスタ → 申請書項目マスタ も 1 対多です。これにより、申請書がどの項目集合を使うかを “書式ID” ひとつで決定できます。
Q: 矢印 “→” の向きはどちら側が “多” ですか?
A: 本試験の凡例では、実線が “1”、矢印の先が “多” を表します。したがって “申請書 → 承認申請” は 申請書(1) から 承認申請(多) です。
A: 本試験の凡例では、実線が “1”、矢印の先が “多” を表します。したがって “申請書 → 承認申請” は 申請書(1) から 承認申請(多) です。
関連キーワード: ワークフロー, 外部キー, 1対多リレーション, データ正規化, 履歴管理
設問2:
図3中のc、dに入れる適切な字句又は式を答えよ。
模範解答
c:承認者情報.承認申請ID = 承認申請.承認申請ID
d:承認者情報.承認者ユーザID = :ユーザID
解説
解答の論理構成
-
一覧画面の要件確認
問題文には「稟議申請の一覧には、自分が申請した稟議申請と、自分が承認者に含まれている稟議申請が表示される。」
とあります。したがって SQL は(申請書.申請者ユーザID = :ユーザID) OR (自分が承認者に含まれている稟議申請)の二つの条件を OR で結合する必要があります。 -
サブクエリの役割
OR 句の後半は、承認者に含まれる稟議書を取得するためのサブクエリです。図3では
sql SELECT DISTINCT 申請書ID FROM 承認者情報 INNER JOIN 承認申請 ON c WHERE dとなっており、- c は 承認者情報と承認申請を結合する条件
- d は ログイン中ユーザが承認者であることを判定する条件
を入れる場所であることが分かります。
-
c の決定
承認者情報エンティティの主な外部キーは
「承認者情報.承認申請ID (FK → 承認申請.承認申請ID)」
です(図2参照)。従って両表を結合する正しい述語は承認者情報.承認申請ID = 承認申請.承認申請IDになります。 -
d の決定
ログインユーザは埋込変数「:ユーザID」で渡されます。
承認者情報エンティティに承認者を示す列は
「承認者情報.承認者ユーザID」
です。よってログインユーザが承認者であることを示す条件は承認者情報.承認者ユーザID = :ユーザIDとなります。 -
結論
以上より- c:承認者情報.承認申請ID = 承認申請.承認申請ID
- d:承認者情報.承認者ユーザID = :ユーザID
が正答です。
誤りやすいポイント
- 「承認申請ID」と「申請書ID」を取り違え、結合キーに 申請書ID を指定してしまう。
- 承認者判定を ユーザ 表で行い、ユーザ.ユーザID = :ユーザID などと書き換えてしまう。これでは「承認者に含まれる」条件になりません。
- DISTINCT を見落として「重複申請書IDの排除が不要」と誤判断し、パフォーマンス要件を落とす。
FAQ
Q: JOIN ではなく WHERE 句だけで結合条件を書いても良いですか?
A: 機能的には成立しますが、内的結合を明示することで可読性と最適化の恩恵を受けられるため、図3のように INNER JOIN ... ON を使うのが推奨です。
A: 機能的には成立しますが、内的結合を明示することで可読性と最適化の恩恵を受けられるため、図3のように INNER JOIN ... ON を使うのが推奨です。
Q: 承認済み(可決・否決)を除外する条件はなぜ承認申請表だけを見るのですか?
A: 稟議書全体の状態を一元管理しているのが「承認申請.承認申請状態」です。稟議書ごとに状態は一つしかないため、他表を参照する必要がありません。
A: 稟議書全体の状態を一元管理しているのが「承認申請.承認申請状態」です。稟議書ごとに状態は一つしかないため、他表を参照する必要がありません。
関連キーワード: INNER JOIN, サブクエリ, 外部キー, DISTINCT, OR 조건
設問3:
図4中のe〜hに入れる適切な字句又は式を答えよ。
模範解答
e:t1.項目値
f:t2.項目値
g:申請書.申請書ID = t1.申請書ID
h:申請書.申請書ID = t2.申請書ID
解説
解答の論理構成
-
図4の SELECT 句
原文では
SELECT 申請書.申請書ID, 申請書.タイトル, e AS 金額, f AS 支払日
とあります。ここで 金額 と 支払日 を取得したい列は、直前の INNER JOIN 申請書項目 t1、INNER JOIN 申請書項目 t2 で結合される別名 t1、t2 から取り出す値です。
申請書項目エンティティの列は【問題文】“申請書項目…項目キーと、項目値の組合せで格納する”と明記されており、実際に欲しいのは 項目値 列です。よって
・[ e ] → t1.項目値
・[ f ] → t2.項目値 -
INNER JOIN 申請書項目 t1 ON g の結合条件
t1 は申請書の各レコードに対応する項目を取得するための表です。E-R 図では【問題文】“申請書 → 申請書項目(1対多)”で結合キーは 申請書ID です。したがって
・[ g ] → 申請書.申請書ID = t1.申請書ID -
INNER JOIN 申請書項目 t2 ON h も同じ理由
t2 も別の項目(支払日など)を取得するために同じ結合が必要です。従って
・[ h ] → 申請書.申請書ID = t2.申請書ID -
以上より回答は
e:t1.項目値
f:t2.項目値
g:申請書.申請書ID = t1.申請書ID
h:申請書.申請書ID = t2.申請書ID
誤りやすいポイント
- 「金額」「支払日」という列が存在すると思い込み、申請書項目 ではなく 申請書 に列を探してしまう。
- ON 句に t1.申請書ID = t2.申請書ID を書いてしまい、申請書と結合せず項目同士を直接結合してしまう。
- 項目キー と 項目値 を取り違え、t1.項目キー を SELECT 句に書いてしまう。
FAQ
Q: なぜ t1 と t2 を別々に結合するのですか?
A: 1つの申請書に複数の項目が登録されているため、金額 用と 支払日 用で2回結合する必要があります。
A: 1つの申請書に複数の項目が登録されているため、金額 用と 支払日 用で2回結合する必要があります。
Q: LEFT JOIN ではなく INNER JOIN で良いのですか?
A: 要件は「可決された稟議申請」の金額・支払日一覧であり、どちらか一方の項目が欠けているレコードは対象外です。よって INNER JOIN が適切です。
A: 要件は「可決された稟議申請」の金額・支払日一覧であり、どちらか一方の項目が欠けているレコードは対象外です。よって INNER JOIN が適切です。
Q: 項目値 は文字列ですが、数値や日付に変換しなくて良いのですか?
A: 出力時点では一覧表示用なので文字列のまま取得し、アプリケーション層で型変換する方針(【問題文】“アプリケーション側で必要に応じて型を変換して用いる”)に沿っています。
A: 出力時点では一覧表示用なので文字列のまま取得し、アプリケーション層で型変換する方針(【問題文】“アプリケーション側で必要に応じて型を変換して用いる”)に沿っています。
関連キーワード: INNER JOIN, SELECT句, 別名(Alias), E-R図, 可変スキーマ
設問4:
本文中の下線①について、どのエンティティに何の属性を追加したかを答えよ。
模範解答
エンティティ:申請書
属性:申請時部署名
解説
解答の論理構成
-
要件の抽出
- 【問題文】には、
「運用開始後、利用者の部署異動や部署名の変更が行われることが想定されるが、システムの画面上で過去の稟議書を参照した際には、申請時の情報が表示される必要がある。」
とあります。ここでいう「申請時の情報」とは、稟議書を提出した当時の部署名です。
- 【問題文】には、
-
現行E-R図の確認
- 図2で「申請書」は 申請者ユーザID を保持し、部署名は次の2段階参照になります。
申請書 → ユーザ (部署ID) → 部署マスタ (部署名) - したがって部署名を画面に出すときは ユーザ.部署ID が示す 部署マスタ.部署名 を取得する設計です。
- 図2で「申請書」は 申請者ユーザID を保持し、部署名は次の2段階参照になります。
-
要件不一致の原因
- もし部署名が後日変更されると、 部署マスタ.部署名 も更新されるため、過去の稟議書を開いても当時の部署名ではなく最新の部署名が表示されます。
- これは先の要件「申請時の情報が表示される必要がある」に反します。
-
解決策の導出
- 部署マスタに履歴テーブルを設けるなど複雑な方法もありますが、問題文は
「あるエンティティに属性を追加すると同時に図3のSQL文も修正することにした」
と限定しています。 - 最小改修で済むのは、稟議書ごとに部署名を固定値として保持すること。すなわち「申請書」エンティティへ新規属性を加える方法です。
- 部署マスタに履歴テーブルを設けるなど複雑な方法もありますが、問題文は
-
追加すべき属性
- 保持する内容は当時の部署名であり、名称例として「申請時部署名」等が妥当です。
- これにより、図3の SELECT 句や JOIN を修正し、部署マスタを参照せず 申請書.申請時部署名 を直接出力すれば要件を満たせます。
-
結論
- エンティティ:申請書
- 属性:申請時部署名
誤りやすいポイント
- 部署マスタに「履歴フラグ」や「有効期間」を追加する答案
→ 要件は「あるエンティティに属性を追加」と限定されているため過剰設計です。 - 「ユーザ」エンティティに部署名をコピーする答案
→ ユーザが部署異動すると新しい部署名に上書きされ、結局過去の部署名が保持できません。 - 「申請書」に部署IDを持たせるだけの答案
→ 部署名変更時に部署IDは変わらないケースが多く、表示用の名称が最新に置き換わってしまいます。
FAQ
Q: なぜ「部署ID」ではなく「申請時部署名」を直接格納するのですか?
A: 部署IDは部署マスタと論理結合するキーであり、部署名が後で変わると表示値も変わってしまいます。文字列として部署名そのものを固定保存すれば、変更の影響を受けません。
A: 部署IDは部署マスタと論理結合するキーであり、部署名が後で変わると表示値も変わってしまいます。文字列として部署名そのものを固定保存すれば、変更の影響を受けません。
Q: 将来、部署階層や異動履歴を詳細に管理したくなった場合は?
A: その際は部署マスタの履歴テーブル化(開始日・終了日をもつ)や、申請書が履歴キーをもつ方式などを追加検討します。ただし本設問の範囲では最小改修が求められています。
A: その際は部署マスタの履歴テーブル化(開始日・終了日をもつ)や、申請書が履歴キーをもつ方式などを追加検討します。ただし本設問の範囲では最小改修が求められています。
Q: 追加属性を入れたことで図3の JOIN はどう変わりますか?
A: INNER JOIN 部署マスタ は不要となり、SELECT 句は 申請書.申請時部署名 を直接出力する形に修正します。
A: INNER JOIN 部署マスタ は不要となり、SELECT 句は 申請書.申請時部署名 を直接出力する形に修正します。
関連キーワード: 正規化, 履歴管理, 外部キー, 冗長性, データ整合性


