戦国IT - 情報処理技術者試験の過去問対策サイト
ブログお知らせお問い合わせ料金プラン

データベーススペシャリスト 2009年 午後1 問03


変更履歴を記録するテーブルに関する次の記述を読んで、設問1〜3に答えよ。

 H銀行では、預金者へのサービス向上を図るために、顧客情報管理に使用している“顧客”テーブルの設計を見直すことになった。 そのため、システム部のG部長の下にプロジェクトチームが組まれ、Fさんが設計を担当することになった。  
〔顧客情報管理の概要〕  顧客情報管理の主な業務内容は、次のとおりである。
(1) 営業店担当者は、顧客からの依頼によって電話番号などの顧客属性情報を変更する。変更した顧客属性情報は、依頼当日から適用される。 同一日に変更を取り消すことはない。 (2) 顧客ごとに設定した優遇レベルによって、ATM(現金自動預け払い機)の時間外利用手数料を割り引くなどのサービスを提供している。 (3) 優遇レベルは、新規登録時の預金額によって決定され、その後は預金残高などの利用状況に基づいて毎月末に決定される。 優遇レベルが変更となる場合は、月末日の夜間バッチ処理によって新たな優遇レベルが設定され、翌月の1日から適用される。  
〔顧客情報管理に使用される主なテーブルの構造〕  顧客情報管理に使用される主なテーブルの構造を図1に示す。 各テーブルの主な列の意味及び制約は、表1に示すとおりである。
データベーススペシャリスト試験(平成21年 午後1 問3 図1)
データベーススペシャリスト試験(平成21年 午後1 問3 表1)
〔“顧客” テーブルの変更〕  1.“顧客” テーブルの構造の変更   Fさんは、顧客属性情報 (顧客名、支店番号、郵便番号、住所、電話番号、優遇レベル)の変更を履歴として記録するために、“顧客” テーブルの構造を図2のように変更した。 追加した列の意味及び制約は、表2に示すとおりである。
データベーススペシャリスト試験(平成21年 午後1 問3 図2)
データベーススペシャリスト試験(平成21年 午後1 問3 表2)
  変更後の“顧客” テーブルには、顧客属性情報の変更履歴が表3のように記録される。   (1) 顧客コードA111111    ① 2008年6月16日に新規の顧客コードA111111が追加された。    ② その日以降、顧客属性情報は変更されていない。   (2) 顧客コードB222222    ① 2007年3月1日に電話番号が変更された。 変更連番が一つ前の行の適用終了日は,NULLから2007年2月28日に設定された。    ② 2007年11月15日に当該顧客との取引がなくなり、顧客コードが削除された。適用終了日にNULLの行がないことが、削除されたことを示している。   (3) 顧客コードC333333    ① 2009年1月15日に電話番号が変更された。    ② 2009年2月1日に優遇レベルが変更された。
データベーススペシャリスト試験(平成21年 午後1 問3 表3)
 2.変更後の“顧客” テーブルへの照会   (1) ある顧客の現在日付の顧客属性情報を1行読み込むために、図3のようなSQL文を設計した。ここで、現在日付を表す予約語をCURRENT_DATEとする。
  (2) ある顧客の属性情報について、優遇レベルが変更された日を調べる(例えば、表4のような結果行を求める) ために、図4のようなSQL文を設計した。
データベーススペシャリスト試験(平成21年 午後1 問3 表4)
 3.顧客属性情報を先日付で変更する処理   現在、月末日の夜間バッチ処理によって優遇レベルを設定しているが、新規顧客の増加に伴い、処理時間に余裕がなくなった。 そこでH銀行では、毎月20日時点の預金残高などに基づいて優遇レベルを決め、優遇レベルが変更となる場合は、20日から月末日までのいずれかの日の夜間バッチ処理によって新たな優遇レベルを設定し、先日付となる翌月の1日から適用することにした。 例えば、2009年5月20日に顧客コードC333333の優遇レベルを2から3に先日付で変更する場合、表5のように変更連番4の行を追加することにした。   また、優遇レベル以外の顧客属性情報の変更についても、顧客からの変更依頼を受け付けた日(以下、変更受付日という)ではなく、変更の適用を開始すべき指定日を適用開始日列に設定することにした。 しかし、顧客情報管理部門からは、“顧客属性情報の変更受付日を漏れなく記録したい” という要望が寄せられている。
データベーススペシャリスト試験(平成21年 午後1 問3 表5)
〔“取引履歴”テーブルの集計処理〕  Fさんは、“顧客” テーブルの構造を変更したことによって、これまで“取引履歴”テーブルと結合して顧客単位に集計処理を行っていたSQL文を見直した。  例えば、2009年4月の支店・顧客別月間預入額を集計するSQL文を図5に示すように設計した。そして、テスト用の“取引履歴”、“口座”、“顧客”の各テーブルにテストデータをロードし、SQL文の実行結果を検証した。 ここで,ISODATE ( )は、日付を表す文字列を DATE型に変換するユーザ定義関数とする。
〔変更後の“顧客” テーブルに関する指摘事項〕  G部長は,Fさんに対し、変更後の“顧客” テーブルに関して、次のように指摘した。
 ① 同一顧客の適用期間は、連続していなければならない。 すなわち、変更連番が1以外の場合の適用開始日は、変更連番が一つ前の行の適用終了日と連続していなければならない(日にちが抜けたり、重なったりしてはならない)。 その制約条件を追加し、制約が守られているかどうかを検証するSQL文を設計すべきである。  ② 優遇レベルを先日付で変更する処理について、更に検討する必要がある。  ③ “顧客属性情報の変更受付日を漏れなく記録したい” という顧客情報管理部門からの要望にこたえていない。  ④ 図5の支店・顧客別月間預入額を集計するSQL文には、誤りがある。

設問1:変更後の“顧客” テーブルを照会するSQL文について(1)(2)に答えよ。

問題文を見る
(1)図3のSQL文中の(a)、(b)に入れる適切な字句を答えよ。(a, bは順不同)

模範解答

a:・適用終了日=CURRENT_DATE   ・適用終了日>=CURRENT_DATE b:適用終了日 IS NULL

解説

解答の導き方

  1. 目的の確認
    図3のSQL文は「SELECT * FROM 顧客 WHERE 顧客コード = :顧客コード AND 適用開始日 <= CURRENT_DATE AND ( (a) OR (b) )」であり、これは「現在日付の顧客属性情報を1行読み込む」ための文です。したがって該当行は「適用開始日 <= CURRENT_DATE」を満たし、かつ CURRENT_DATE が当該行の有効期間内にある必要があります。
  2. 有効期間の定義を問題文から読み取る
    問題文に「適用終了日が未定の場合は、NULLが設定される」とあります。さらに表の例(例えば変更連番3の適用終了日が2009-05-31で変更連番4の適用開始日が2009-06-01となっている先日付の例)から、有効期間は開始日を含み終了日も含む連続した日付範囲で扱われていることがわかります(前行の適用終了日と次行の適用開始日が連続している)。
  3. CURRENT_DATEが有効期間に含まれる条件を式にする
    日付範囲 [適用開始日, 適用終了日] にCURRENT_DATEが含まれるための条件は次のとおりです。
    • 適用開始日 <= CURRENT_DATE(図3の既存条件)
    • そして(適用終了日 >= CURRENT_DATE)または(適用終了日 IS NULL)であること。
      • 「適用終了日 IS NULL」は、終了日未定(現行行)の扱いを確実に取り込むために必要です。
      • 「適用終了日 >= CURRENT_DATE」は、適用終了日が設定されている行のうち、当日を含む行を取り込むための条件です。
  4. したがって図3中の(a),(b)に入る字句は次になります。
    a:適用終了日 >= CURRENT_DATE 又は 適用終了日 = CURRENT_DATE
    b:適用終了日 IS NULL
(注)解答例は (a) に「適用終了日=CURRENT_DATE」「適用終了日>=CURRENT_DATE」の両方を挙げています。設問1の時点では先日付の変更による行がないため、適用終了日が設定されている行で当日を含むのは、適用終了日が当日の行に限られ、「= CURRENT_DATE」でも正しく1行を読み込めます。先日付の行も考慮して一般化するなら「>= CURRENT_DATE」です。

誤りやすいポイント

  • 「適用終了日 = CURRENT_DATE」を誤りと決めつける
    設問1の時点では先日付の行がないので「= CURRENT_DATE」も正解です(解答例も両方を挙げています)。先日付の変更を考える設問2以降では「>= CURRENT_DATE」が必要になります。
  • NULLの扱いを忘れる誤り
    SQLでの比較はNULLに対して真にならないため、「適用終了日 >= CURRENT_DATE」だけだと終了日がNULL(現行の有効行)であるレコードが除外されます。必ず「適用終了日 IS NULL」を明示するか、代替手段でNULLを扱う必要があります。
  • 「> CURRENT_DATE」を使う誤り
    終了日がちょうど当日の行(当日まで有効)を取り落とします。図の運用から終了日は当日を含むため、">=" を用いるべきです。
  • 日時成分による比較ミス
    カラムが日時(時刻を含む)型の場合は 時刻成分 によって期待と異なる結果になることがあります。図中のCURRENT_DATEは日付を表す予約語なので日付単位の比較を前提にしていますが、実装時は型を揃える注意が必要です。

FAQ

Q: 「適用終了日 IS NULL OR 適用終了日 >= CURRENT_DATE」と「適用終了日 >= CURRENT_DATE OR 適用終了日 IS NULL」はどちらでもよいですか?
A: 論理的には等価であり、どちらを先に書いても結果は同じです。ただし実装やデータベースの最適化観点で実行計画が変わる場合があるため、性能を意識する場合は実行計画で確認してください。
Q: COALESCE やNVLでNULLを大きな日付に置き換えて一つの比較式にまとめても良いですか?
A: 機能的には有効です(例: COALESCE(適用終了日, DATE '9999-12-31') >= CURRENT_DATE)。ただし関数をカラムに適用するとインデックスが使われにくくなる場合があるため、性能要件がある場合は注意が必要です。
Q: 削除された顧客(適用終了日のみが設定されNULL行が無い)の現在日照会はどうなりますか?
A: 削除日以降は該当顧客に対してCURRENT_DATEに合致する行が存在しないため、図3の条件では行は返りません。削除の扱いは業務要件に従って別途設計する必要があります。

関連キーワード: NULL処理、日付比較、範囲条件、先日付更新、論理演算子

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

設問1:変更後の“顧客” テーブルを照会するSQL文について(1)(2)に答えよ。

問題文を見る
(2)図4のSQL文中の(c)、(d)に入れる適切な字句を答えよ。

模範解答

c:X.変更連番 + 1 d:X.優遇レベル

解説

解答の論理構成

  1. 目的確認
    図4のSQL文は「優遇レベルが変更された日を調べる」ものです。したがって直前行と優遇レベルが異なる行だけを抽出する必要があります。
  2. 自己結合のキー
    where句に
    AND (c) = Y.変更連番
    とあるため、Y側が「X側の次の連番」であることを示す式を入れます。履歴テーブルは表2で「変更連番…1ずつ増加する整数が付与される。連番に抜けはない。」と定義されているので、一意に次行を示すのは「X.変更連番 + 1」です。
  3. 優遇レベル差異の判定
    同一行を結んだだけでは優遇レベルが変わったか分かりません。問題文には「優遇レベルが変更された日を調べる(例えば、表4のような結果行を求める)」と書かれています。そこで (d) に優遇レベルの不一致条件を置きます。XとYは隣接行なので、異なるときだけ抽出すればよく、式は「X.優遇レベル」と「Y.優遇レベル」を比較します。where句ではY.優遇レベル と比較するため (d) には「X.優遇レベル」が入ります。
  4. 以上より
    c: X.変更連番 + 1
    d: X.優遇レベル

誤りやすいポイント

  • 変更連番のずらしかたを「−1」としてしまう
    Xが最新行、Yが前行と誤解すると逆になります。where句の (c) = Y.変更連番 の向きを確認しましょう。
  • 優遇レベル比較で「=」を使い抽出できない
    変更を検出するので不一致条件 (≠) が必要です。
  • 変更連番に「NULL存在可能」と勘違い
    表2に「連番に抜けはない」と明記されています。NULLは入りません。

FAQ

Q: 変更連番が飛ぶ可能性はまったくありませんか?
A: 表2の定義で「1から始まり1ずつ増加する整数が付与される。連番に抜けはない。」と規定されているため、論理的に飛びは起こりません。
Q: 最新の優遇レベルだけ取得したい場合はどうすればよいですか?
A: 顧客コードごとに MAX(変更連番) をサブクエリやウィンドウ関数で求め、その行を抽出する方法が一般的です。
Q: テーブル分割(履歴テーブルと現行テーブル)にしない利点は?
A: 1つのテーブルで履歴と現行を管理すれば、更新・参照ロジックを共通化できる反面、パフォーマンスや制約管理は自己結合で解決する必要があります。

関連キーワード: 自己結合、更新履歴管理、差分抽出

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

設問2:〔変更後の“顧客” テーブルに関する指摘事項〕 ①〜③について、(1)〜(4)に答えよ。

問題文を見る
(1)指摘事項 ①に対応するために、適用終了日がNULLでも削除日付でもない行のうち、適用期間が連続していない行を読み込むためのSQL文を設計したい。 次のSQL文中の(e)、(f)に入れる適切な字句を答えよ。  ここで,NEXT_DAY()は、引数とした日付の翌日付を求めるユーザ定義関数とする。なお、(c)には設問1の(2)と同じ答えが入る。 データベーススペシャリスト試験(平成21年 午後1 問3 設問2-1)

模範解答

e:X.顧客コード f:Y.適用開始日

解説

解答の導き方

目的は、同一顧客について「適用期間が連続していない行」を抽出することです。与えられたSQLの骨格は、ある行Xに対して「次の行Yが存在していて、その開始日がXの終了日の翌日と異なる」場合を検出する構造になっています。これを順を追って確認します。
  1. 次の行Yをどう特定するか
     表の定義に「変更連番は、1から始まり1ずつ増加する整数が付与される。連番に抜けはない。」とあります。したがって、ある行Xの次の変更連番は「X.変更連番 + 1」であり、次の行Yはこの連番を持つ行です。これが(c)に入る式の根拠です。
  2. 同一顧客かどうかの照合
     指摘事項①の条件は「同一顧客の適用期間は、連続していなければならない。」ですから、比較対象のYはXと同じ顧客でなければなりません。SQLの内側でYの顧客をXに合わせるため、比較式として「X.顧客コード = Y.顧客コード」を使います。これが(e)に入るべき字句です。
  3. 連続の判定方法
     「日にちが抜けたり、重なったりしてはならない」とあるので、連続しているとは「次の行の適用開始日が、直前行の適用終了日の翌日と一致する」ことを意味します。直前行の終了日の翌日を求めるためにNEXT_DAY(X.適用終了日) が与えられているため、連続していない条件はNEXT_DAY(X.適用終了日) <> Y.適用開始日 になります。これが(f)に入る字句です。
以上より、(c)はX.変更連番 + 1 (設問1(2)と同じ)、(e)はX.顧客コード、(f)はY.適用開始日 が妥当です。
最終回答(この設問で求められた(e)、(f)の値)
  • e:X.顧客コード
  • f:Y.適用開始日

誤りやすいポイント

  • (c)をX.変更連番 − 1としてしまう誤り:次の行を探すのに「−1」を使うと前の行を探してしまい、論理が逆になります。表の「連番に抜けはない」を根拠に「+1」を使う必要があります。
  • 終了日と開始日を直接比較してしまう誤り:連続の定義は「終了日の翌日」と「次の開始日」が一致することなので、NEXT_DAYを使わずにX.適用終了日 = Y.適用開始日 とするとオフバイワン(1日ずれる)になります。
  • XとYの顧客照合を忘れる誤り:複数顧客のデータが混在するため、必ず同一顧客(顧客コード)で照合しないと誤検出します。
  • NULLの扱いを誤る誤り:現行適用中の行は適用終了日がNULLなので、対象外にする条件(X.適用終了日 IS NOT NULL)が必要です。
  • 削除行(顧客削除時に適用終了日に削除日付が入る)の扱いの誤解:このSQLは「次の行が存在するか」を EXISTS で確認しているため、末尾の削除行(次の行がない行)はそもそも検出対象になりません。削除行も検出したい場合は別条件が必要です。

FAQ

Q: NEXT_DAYを使う理由は何ですか?
A: 「連続している」とは「前の適用終了日の翌日が次の適用開始日と一致する」ことを意味します。したがって終了日の翌日を明示的に求めるNEXT_DAY(X.適用終了日) とY.適用開始日 を比較する必要があります。単に日付をそのまま比較すると1日ずれる誤りになります。
Q: EXISTS を使う利点は何ですか?
A: EXISTS は「次の行が存在して、かつ条件を満たすか」を効率的に判定します。JOIN を使うと複数行が結合されて集計や重複処理の影響を受けやすく、次の行が存在しないケース(末尾行)を扱う際に追加の注意が必要になります。
Q: 削除日である行(顧客が削除された最後の行)も検出したいときはどうしますか?
A: 現行の構造では末尾の削除行には「次の行」が存在しないためこのSQLでは検出されません。削除行も検出対象にしたければ、例えば「適用終了日が削除日付であることを示す別列やフラグ」を設けるか、顧客ごとの最大変更連番を算出して末尾行を特定し、そこに別途不連続の条件を適用するような追加ロジックが必要です。

関連キーワード: 履歴管理、時系列データ整合性、日付演算、存在性検査、連番管理

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

設問2:〔変更後の“顧客” テーブルに関する指摘事項〕 ①〜③について、(1)〜(4)に答えよ。

問題文を見る
(2)指摘事項②を確認するために、顧客コードC333333の電話番号が2009年5月25日に変更された場合を想定して、“顧客” テーブルに次の表のように変更連番5の行を追加した。 しかし、指摘事項 ① に対応していないので、図3のSQL文では、例えば、CURRENT_DATEが2009年5月25日であるとき、想定した結果を得られない。 どのような結果になるのか、15字以内で述べよ。 データベーススペシャリスト試験(平成21年 午後1 問3 設問2-2)

模範解答

・結果行が複数行になる。 ・SQL文の実行が失敗する。

解説

解答の導き方

解答(15字以内): 結果行が複数行になる
導き方(手順を省かず丁寧に説明します)
  1. 図3のSQLの意図を確認します。図3は「適用開始日 <= CURRENT_DATE」を条件にし、さらにもう一つの条件群((a) または (b))で現在日に有効な行を選ぶ設計です。実務上この(a)/(b)は通常「適用終了日 IS NULL」または「適用終了日 >= CURRENT_DATE」を意味します。つまり図3は「適用開始日 <= CURRENT_DATEかつ (適用終了日 IS NULLまたは 適用終了日 >= CURRENT_DATE)」を満たす行を選ぶ意図です。
  2. C333333の該当行を条件と照らします(問題文の表の該当行をそのまま参照します)。
    • 変更連番3: 適用開始日2009-02-01、適用終了日2009-05-31
      → 適用開始日 <= 2009-05-25を満たす(2009-02-01 ≤ 2009-05-25)、適用終了日 >= 2009-05-25も満たす(2009-05-31 ≥ 2009-05-25)。
    • 変更連番5: 適用開始日2009-05-25、適用終了日2009-05-31
      → 適用開始日 <= 2009-05-25を満たす(等号も含む)、適用終了日 >= 2009-05-25も満たす(2009-05-31 ≥ 2009-05-25)。
  3. したがって図3の条件を満たす行は変更連番3と変更連番5の2行になるため、図3のSQLは複数行を返します。図3は「現在日付の顧客属性情報を1行読み込む」目的で設計されているため、この状況は想定外です。
  4. 補足(実行結果の扱いについて): 生のSELECT文は複数行の結果セットを返して実行自体は成功することが多いですが、図3のように「1行を期待する処理」(SELECT INTOや単一行を前提としたホスト言語の処理)で呼ぶと「単一行を期待しているのに複数行来た」ことで実行時エラー(単一行想定の処理で失敗する)となる可能性があります。したがって試験での短答は「結果行が複数行になる」が基本解答で、実務的な注意として「単一行期待の処理では実行時エラーになる場合がある」と補足説明する必要があります。

誤りやすいポイント

  • 「適用開始日 <= CURRENT_DATE」の等号(等しい日付も含む)を見落とし、当日変更を選ばないと誤判断する。
  • 重複(適用期間の重なり)があると複数行になる点を見落とす(今回の変更連番3と5が重複)。
  • 生のSELECTは複数行返しても必ずしもSQLが『失敗する』とは限らない点を混同する(ただし単一行期待の文脈ではエラーになる)。
  • 変更連番4(適用開始日2009-06-01)は2009-05-25の時点では選ばれない点を誤って含める。

FAQ

Q: 図3のSQLを変えずに必ず1行にする方法はありますか?
A: SQL側で最後に適用された行だけを取るようにすれば良いです(例: ORDER BY 適用開始日 DESC または ORDER BY 変更連番 DESC を付けて先頭の1行を取得)。ただし根本対策はデータの不整合(期間の重複)を防ぐことです。
Q: データの不整合(期間の重複)はどう検出すればよいですか?
A: 顧客テーブルを自己結合して、同一顧客の異なる行ペアで開始日・終了日が重なるものを探します。ロジックは「a.適用開始日 <= b.適用終了日 かつb.適用開始日 <= a.適用終了日」を満たすペアを検出する、という形です(NULLの取り扱いは無期限とみなす等の考慮が必要です)。
Q: どちらを優先すべきですか、SQL修正とデータ整合性のどちらか?
A: 優先はデータ整合性の確保です。SQLで回避することは可能ですが、根本的には「同一顧客の適用期間は連続かつ非重複である」という制約をデータベース側で担保する(制約・トリガ・バッチ検査など)べきです。

関連キーワード: 履歴管理、有効期間、時相データ、重複検出、単一行取得

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

設問2:〔変更後の“顧客” テーブルに関する指摘事項〕 ①〜③について、(1)〜(4)に答えよ。

問題文を見る
(3)指摘事項②に対応するために、変更連番の列名を“適用順番”に、その意味を“適用開始日の順番”に変更し、指摘事項 ①の制約条件を追加した。このとき、顧客コードC333333の顧客属性情報の列値について、次の表中の(g)〜(j)に入れる適切な字句を答えよ。 データベーススペシャリスト試験(平成21年 午後1 問3 設問2-3)

模範解答

(g):333-3333 (h):2 (i):333-3333 (j):3

解説

解答の論理構成

  1. 制約の確認
    • 指摘事項①より「変更連番が1以外の場合の適用開始日は、変更連番が一つ前の行の適用終了日と連続していなければならない」(設問2(3) では変更連番を適用順番に読み替える)
  2. イベントの整理
    • “2009-05-24” までは電話番号 “333-2222”・優遇レベル “2”
    • “2009-05-25” に電話番号変更を受付(優遇レベルはまだ “2”)
    • “2009-06-01” から優遇レベル “3” を適用
  3. 行の割付
    • 3行目が “2009-02-01” ~ “2009-05-24” レベル “2” で確定
    • 4行目は受付日 “2009-05-25” を起点に電話番号 “333-3333”・優遇レベル “2”・適用終了日 “2009-05-31”
    • 5行目は先日付 “2009-06-01” 開始、電話番号 “333-3333”・優遇レベル “3”・適用終了日 NULL
  4. 値の確定
    よって
    (g) = “333-3333” (h) = “2” (i) = “333-3333” (j) = “3”

誤りやすいポイント

  • 先日付処理を1行で済ませようとして期間が重複/欠落する
  • 電話番号変更と優遇レベル変更を同じ行で更新し、受付日が記録できなくなる
  • 適用終了日NULLの行は必ず1行だけという暗黙ルールを忘れる

FAQ

Q: 適用終了日がNULLの行は常に最新行ですか?
A: はい。同一顧客に対し適用終了日がNULLの行は1行のみで、最新の属性値を保持します。
Q: 先日付の優遇レベルを更新する際、適用開始日はいつに設定すれば良いですか?
A: 実運用で開始させたい日(例では “2009-06-01”)。受付日と異なる場合は受付日から開始日-1日までを別行で管理し、期間を連続させます。

関連キーワード: 履歴管理、適用開始日、先日付更新、NULL終端行、連続期間制約

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

設問2:〔変更後の“顧客” テーブルに関する指摘事項〕 ①〜③について、(1)〜(4)に答えよ。

問題文を見る
(4) 指摘事項 ③に対応するために、(3)の変更を行った上で、変更受付日の列を追加し、その意味を次のように定義した。 データベーススペシャリスト試験(平成21年 午後1 問3 設問2-4)
 しかし、この変更受付日の列の追加だけでは、“顧客属性情報の変更受付日を漏れなく記録したい” という要望にこたえられない場合がある。 どのような場合にこたえられないのか、35字以内で述べよ。

模範解答

・同じ適用開始日に異なる変更受付日の顧客属性情報が存在する場合 ・先日付で設定した適用開始日よりも前に顧客コードを削除する場合

解説

解答の導き方

まず問題文の定義に注目します。変更受付日の意味は「当該顧客の属性情報(優遇レベル以外)の変更依頼を受け付けた日付、又は優遇レベルを設定した日付」とあります。一方で、変更の記録方法については「変更の適用を開始すべき指定日を適用開始日列に設定することにした」とあり、適用開始日と変更受付日が一致しない(先日付)ケースが想定されています。
顧客テーブルは各行がある期間における属性の状態を表し、各行に単一の変更受付日列を追加する設計になっています。ここから次の二つの状況で「変更受付日の列だけでは漏れなく記録できない」ことが導けます。
  1. 同一の適用開始日に複数の変更依頼がある場合
     複数の属性変更(例えば氏名変更と電話番号変更)が、受付日が異なるにもかかわらず適用開始日を同一日に指定されることがあります。顧客テーブルは「ある適用開始日からの状態」を1行で表すため、その行には変更受付日を1つしか格納できません。別行として同一適用開始日を持つ行を追加すると、指摘事項①の「同一顧客の適用期間は、連続していなければならない」に抵触したり、期間が重複・欠落するため不整合が生じます。したがって、同一適用開始日に異なる受付日を持つ複数の依頼を漏れなく残せません。
     (例:5月1日に氏名変更受付、5月10日に電話変更受付、いずれも適用開始日を6月1日に指定した場合、顧客テーブルの1行に2つの受付日を入れられない。)
  2. 先日付で設定した適用開始日より前に顧客が削除される場合
     問題文は「顧客コードが削除されたときは、当該顧客行は削除されず、削除日付が設定される」としています。先日付の変更は適用開始日が将来日付の行を作成して記録する運用例が示されていますが、顧客がその適用開始日より前に削除されると、削除処理の結果(削除日付の設定や将来行の無効化・整理)によっては、先に作成した「適用開始日=将来日付」の行が最終データ上残らない、あるいは意味を持たない状態になる可能性があります。その結果、その行に記録していた変更受付日が最終的に参照できなくなる場合があります。
     (例:5月20日に6月1適用で行を追加して受付日を記録したが、5月25日に顧客が削除されると、最終データに先日付行が残らないため受付日の記録が失われる可能性がある。)
以上より、追加した列だけでは次の場合に要望を満たせないと結論できます。
  • 同じ適用開始日に異なる変更受付日の顧客属性情報が存在する場合
  • 先日付で設定した適用開始日より前に顧客コードを削除する場合

誤りやすいポイント

  • 「適用開始日=変更受付日」と混同する。先日付で適用開始日を指定する点を見落とすと誤答する。
  • 同一の適用開始日は複数行で表現できると安易に考える。指摘事項①の連続性制約で矛盾が生じる。
  • 削除の扱いを「行を単に追加する」と誤解する。問題文は「当該顧客行は削除されず、削除日付が設定される」としていることを忘れない。
  • 「変更受付日」を顧客テーブルの単一列で済ませればよいと考えるが、イベント(受付)の粒度で残すなら別テーブル(ログ)が必要になる点を見落とす。

FAQ

Q: 同じ受付日で複数の属性を同時に変更する場合は問題ないですか?
A: はい。受付日が同一であれば1行の変更受付日で表現できるため顧客テーブルの列で対応可能です。
Q: 漏れなく記録するための現実的な対処は何ですか?
A: 変更受付を1回のイベントとして記録する別テーブル(変更受付ログ)を作り、(顧客コード、変更対象、受付日、指定適用開始日など)を行単位で保持するのが確実です。顧客テーブルは状態(有効期間)を保持し、受付ログでトレーサビリティを取る設計が望ましいです。
Q: 優遇レベルの扱いはどう違いますか?
A: 定義にあるとおり、優遇レベルについては変更受付日列に「優遇レベルを設定した日付」を入れる運用です。優遇レベル設定はバッチで行われるため受付日相当が別意味(設定日)になる点に注意してください。

関連キーワード: 履歴管理、有効期間管理、監査ログ、先日付処理、変更受付記録

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

設問3:〔変更後の“顧客” テーブルに関する指摘事項〕 ④について、答えよ。

問題文を見る
 指摘事項④に対応するために、具体的なテストデータを用いて検討した。適用期間中、月に1回以上の預け入れが存在するA〜Iの顧客について、図5のSQL文を利用して集計した月間預入額の結果を表に整理した。 表中の顧客コード欄に該当する顧客コードをA〜Iから選んですべて答えよ。 該当する顧客コードがない場合は、空欄にすること。  なお,SQL文の結果行が存在しなかった顧客の場合、月間預入額を0円とする。また、適用期間は連続していて、日にちが抜けたり、重なったりしていることはない。各顧客の支店番号、顧客コード、顧客名は変更されないものとする。 データベーススペシャリスト試験(平成21年 午後1 問3 設問3(図))
データベーススペシャリスト試験(平成21年 午後1 問3 設問3(表))

模範解答

データベーススペシャリスト試験(平成21年 午後1 問3 設問3解答)

解説

解答の導き方

まず図5のSQLで顧客(Z)を絞り込んでいる条件を確認します。図にある絞り込みの該当箇所は次の2行です。
「AND ISODATE('2009-04-01')<= Z.適用開始日」
「AND ( Z.適用終了日<=ISODATE('2009-04-30') OR Z.適用終了日 IS NULL )」
この2行をそのまま読むと、図5は「Z行の適用開始日が2009-04-01以降である」かつ「適用終了日が2009-04-30以前であるか、あるいは適用終了日がNULLで継続中である」行だけを選んでいます。言い換えると「Z行の適用開始日 >= 2009-04-01」が必須条件になっており、4月1日より前に開始して4月を含む行は除外されます。
次に結合の仕方を見ます。図5は「FROM 取引履歴 X、口座 Y、顧客 Z」かつ「Y.顧客コード=Z.顧客コード」で結合しています(図中にその等値結合がある)。しかし X.取引日 と Z.適用開始日/適用終了日 を直接結ぶ条件が入っていません。つまり、ある顧客について図5のZ抽出条件を満たすZ行が複数あると、月内の各取引(Xの行)はその顧客の選ばれた全てのZ行と結合されます。結果として同じ取引金額が複数回加算される可能性があります。
この構造がもたらす結果は単純に3通りしかありません。
  • 図5のZ抽出条件を満たすZ行が0件 → SQLの結果行が存在しない(問題文の指示に従えばその顧客の月間預入額は0円扱いになる)。
  • Z行が1件 → 各取引はちょうど1回だけ結合されるので、SUMは正しい値になる。
  • Z行が2件以上 → 各取引が複数回結合されるため、SUMは正しい値よりも大きくなる(重複集計)。
重要:このクエリ構造では「正しい値より少なくなるが0ではない」という中間のパターンは発生しません。なぜなら、抽出されたZ行が1件以上あれば、その顧客に対する全ての取引は少なくとも1回は結合され、かつ選ばれたZ行の数だけ掛けられる(=1倍かそれ以上)ためです。
以上のルールに沿って、図(時間は左→右、○:適用開始日、●:適用終了日、▶:適用終了日がNULL)から、図5のZ抽出条件(適用開始日が4月1日以降、かつ適用終了日が4月30日以前又はNULL)を満たすZ行が各顧客で何件あるかを判断します。
  • 月間預入額は正しい(Z行が1件):
    • A:3本の線分のうち、4月1日以降に始まり適用終了日がNULLの線分(4月中旬に○、右端が▶)だけが条件を満たす。
    • D:4月1日の直後に○があり、右端が▶の線分が1本だけで、これが条件を満たす。
    • F:4月30日より後に○があり、右端が▶の線分が1本だけで、これが条件を満たす。
    • G:4月1日の直後に○、4月30日の手前に●がある線分が1本だけで、これが条件を満たす。
  • 正しい月間預入額よりも多くなる(Z行が2件以上 → 重複集計):
    • B:4月1日より前に始まる線分は除外されるが、4月中に始まって4月中に終わる線分と、4月中に始まり右端が▶の線分の2本が条件を満たす。
    • E:3本の線分がいずれも4月1日以降に始まり、4月中に終わるか右端が▶なので、3本とも条件を満たす。
  • 預け入れがあるにもかかわらず、月間預入額が0円である(Z行が0件 → 結果行が生成されない):
    • C:4月1日より前に○があり、右端が▶の線分1本だけ。適用開始日が4月1日より前なので除外される。
    • H:4月1日より前に○、4月1日の直後に●がある線分1本だけ。適用開始日が4月1日より前なので除外される。
    • I:4月中に○、4月30日より後に●がある線分1本だけ。適用終了日が4月30日より後でNULLでもないので除外される。
以上より設問の分類は次の通りです(問題文の判定ルールに従って表現しています)。
  • 月間預入額は正しい。:A、D、F、G
  • 正しい月間預入額よりも多くなる。:B、E
  • 正しい月間預入額よりも少なくなるが、0円ではない。:(該当なし)
  • 預け入れがあるにもかかわらず、月間預入額が0円である。:C、H、I

誤りやすいポイント

  • 図5の2つの日付条件を読み間違え、「適用期間が4月を含めばよい」と誤解する点。実際は「適用開始日 >= 2009-04-01」が必須で、4月開始以前に始まって継続している行は除外されます。
  • 取引日と顧客の適用期間を結ぶ条件(X.取引日 とZ.適用開始日/適用終了日)を入れ忘れている点に気づかないこと。これがないと取引がZの複数行と結合されて重複集計が起こります。
  • GROUP BY のキー(Z.支店番号、Z.顧客コード、Z.顧客名)が顧客ごとに不変である前提を見落とし、複数Z行が選ばれてもグループは1つにまとまり合算される点を理解していないこと。
  • 「正しいより少なくなるが0ではない」パターンを想定して誤って選ぶこと。図5の構造ではそのパターンは発生しないため、選択肢は「多い/正しい/0(行なし→0円)」のいずれかになります。

FAQ

Q: 図5のSQLをどう直せば良いですか?
A: 取引日と顧客の適用期間が重なる行だけを結合する条件を追加します。月全体で集計するなら、顧客行と集計対象期間が重なることを判定する条件に変えます。例えば月の範囲を使うなら
「Z.適用開始日 <= ISODATE('2009-04-30') AND ( Z.適用終了日 >= ISODATE('2009-04-01') OR Z.適用終了日 IS NULL )」
取引ごとに正確に結合するなら、JOIN/WHERE に
「Z.適用開始日 <= X.取引日 AND ( Z.適用終了日 >= X.取引日 OR Z.適用終了日 IS NULL )」
を入れて、各取引がそのZ行の期間内にある場合にのみ結合させます。
Q: なぜ複数のZ行が選ばれると必ず「多くなる」だけで「少なくなる」ことはないのですか?
A: 図5の構造では、Z行が0件なら結果行自体が存在しない(問題文の扱いで0円)。Z行が1件以上あれば、取引は選ばれたすべてのZ行と結合されるため、各取引は最低1回、複数選ばれれば複数回加算されます。したがって「一部の取引だけが結合され、結果的に少なくなる」という状態は生じません。
Q: 改善案としてはどこを優先修正すべきですか?
A: まずはX.取引日 とZの適用期間を結ぶ結合条件を追加して取引毎に正しく結合されるようにすることが最優先です。次にZ抽出条件自体(月に対する包含判定)を見直し、月の開始/終了との期間重なりで行を選ぶようにします。

関連キーワード: 期間オーバーラップ、等値結合、重複集計、NULL判定、日付比較

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

戦国ITクイズ機能

\ せっかくなら /

データベーススペシャリストを
クイズ形式で学習しませんか?

クイズ画面へ遷移する→

すぐに利用可能!

©︎2026 情報処理技術者試験対策アプリ

このサイトについてブログプライバシーポリシー利用規約特商法表記開発者について