基本情報技術者 2016年 秋期 午後 問03
従業員の通勤情報を管理する関係データベースに関する次の記述を読んで、設問1~4に答えよ。
Y社では、従業員の1か月分の交通費の合計を通勤手当として支給している。交通費は、通勤に公共の交通機関を利用している場合は通勤経路の各区間運賃であり、自家用車を利用している場合は燃料費などの諸経費である。
通勤手当は図1に示す表で管理していたが、より詳細に情報を管理するために、図2のとおり変更した。下線付きの項目は、主キーを表す。


設問1:
問題文を見る 変更後の表を用いて通勤手当に関するデータを集計する。次の記述中のに入れる正しい答えを、解答群の中から選べ。
従業員ごとの通勤手当を求めるには、aグループ化して、集合関数bを用いればよい。また、交通機関ごとの利用者数を求めるには、cグループ化して、集合関数dを用いればよい。
a, cに関する解答群
ア:交通機関表を交通機関コードで
イ:従業員表を従業員番号で
ウ:通勤費表を交通機関コードで
エ:通勤費表を従業員番号で
b, dに関する解答群
ア:AVG
イ:COUNT
ウ:MAX
エ:SUM
模範解答
a:エ、b:エ、c:ウ、d:イ
解説
解答の導き方
図2では、従業員の氏名や住所を管理する「従業員表」と、従業員ごとの交通費を管理する「通勤費表」が分かれています。通勤費表には、従業員番号、交通機関コード、交通費があります。従業員が複数の交通機関を使う場合は、その交通機関ごとに行が分かれます。
従業員ごとの通勤手当を求めるには、同じ従業員の交通費を合計します。そのため、交通費の記録がある「通勤費表」を従業員番号でグループ化します。グループ化とは、指定した項目の値が同じ行をまとめることです。
たとえば、図2の例では、従業員番号「00980125」の交通費として「4800」と「5850」が記録されています。この従業員の通勤手当は、これらを足した金額です。複数の金額を合計する集合関数(グループごとの値を一つにまとめる計算)を使うので、aは「通勤費表を従業員番号で」、bは「SUM(sum:合計)」です。解答群では、それぞれエ、エに当たります。
次に、交通機関ごとの利用者数を求めます。利用者の情報は、従業員番号と交通機関コードが記録されている通勤費表にあります。交通機関コードが同じ行をまとめれば、その交通機関を利用している従業員の記録を集められます。まとめた行数を数えるため、cは「通勤費表を交通機関コードで」、dは「COUNT(count:件数)」です。解答群では、それぞれウ、イに当たります。
交通機関表には、交通機関コードと交通機関名が記録されています。コードに対応する名前を調べるための表なので、利用者数を数える元の表としては使いません。
誤りやすいポイント
- 通勤手当の合計では、従業員番号でまとめるだけでなく、交通費を合計する必要があります。件数を数えるCOUNTでは、金額は求められません。
- 交通機関ごとの利用者数では、交通機関コードでまとめます。従業員番号でまとめると、交通機関ごとの人数にはなりません。
- 交通機関表には交通機関名が載っていますが、従業員の利用記録はありません。利用者数を求めるときは、利用記録がある通勤費表を選びます。
- AVG(average:平均)は平均値、MAX(maximum:最大値)を求める関数です。交通費の合計にも、利用者数にも使いません。
FAQ
Q: 従業員表を従業員番号でグループ化しても、通勤手当は求められませんか?
A: 従業員表には氏名や住所などがあり、交通費の金額はありません。通勤手当を計算するには、交通費が記録された通勤費表を使います。
A: 従業員表には氏名や住所などがあり、交通費の金額はありません。通勤手当を計算するには、交通費が記録された通勤費表を使います。
Q: COUNTは何を数えていますか?
A: この問題では、交通機関コードごとにまとめた通勤費表の行数を数えています。通勤費表の1行が、その従業員の交通機関の利用記録に対応しているため、行数から利用者数を求められます。
A: この問題では、交通機関コードごとにまとめた通勤費表の行数を数えています。通勤費表の1行が、その従業員の交通機関の利用記録に対応しているため、行数から利用者数を求められます。
Q: SUMとCOUNTの違いは何ですか?
A: SUMは金額などの数値を足し合わせます。COUNTは行や値の件数を数えます。通勤手当の計算にはSUM、利用者数の計算にはCOUNTを使います。
A: SUMは金額などの数値を足し合わせます。COUNTは行や値の件数を数えます。通勤手当の計算にはSUM、利用者数の計算にはCOUNTを使います。
関連キーワード: 関係データベース、グループ化、集合関数、SUM、COUNT
設問2:
問題文を見る 通勤にバスを利用している従業員の従業員番号と交通機関名を表示する。ここで、交通機関コードは3文字の固定長文字列であり、バスの交通機関コードだけが文字“B”で始まる。次のSQL文のに入れる正しい答えを、解答群の中から選べ。
SELECT 通勤費表.従業員番号, 交通機関表.交通機関名
FROM 通勤費表, 交通機関表
WHERE 通勤費表.交通機関コード = 交通機関表.交通機関コード AND e
eに関する解答群
ア:通勤費表.交通機関コード IN ('B00', 'B99')
イ:通勤費表.交通機関コード LIKE 'B%'
ウ:通勤費表.交通機関コード LIKE 'B_'
エ:通勤費表.交通機関コード LIKE '_B%'
模範解答
e:イ
解説
解答の導き方
このSQLは、通勤にバスを利用している従業員について、従業員番号と交通機関名を表示するものです。SQL(Structured Query Language:データベースにデータを問い合わせたり操作したりするための言語)の条件を順に見ていきます。
まず、FROM句には通勤費表と交通機関表があります。WHERE句の「通勤費表.交通機関コード = 交通機関表.交通機関コード」は、両方の表で交通機関コードが同じ行を対応付ける条件です。このように複数の表の情報を対応付けることを、表の結合といいます。
次に、問題文には「バスの交通機関コードだけが文字“B”で始まる」とあります。そのため、交通機関コードの先頭が「B」である行を選べば、バスを利用している従業員を抽出できます。
文字列の一部のパターンを調べるLIKE演算子では、%は「0文字以上の任意の文字列」を表します。したがって、LIKE 'B%' は「先頭がBで、その後ろは任意の文字列」という条件です。交通機関コードは3文字の固定長文字列なので、先頭のBに続く2文字が何であっても、この条件に合います。
各選択肢を確認します。
- アのIN ('B00', 'B99') は、指定した2種類のコードだけに一致します。Bで始まるすべてのコードを選べるわけではありません。
- イのLIKE 'B%' は、先頭がBであるコードを選べます。
- ウのLIKE 'B_' は、_を文字として扱うなら「Bの次にアンダースコアがある文字列」を表し、任意の2文字を表すものではありません。
- エのLIKE '_B%' は、_を文字として扱うならアンダースコアで始まる文字列を表します。Bで始まるコードを選ぶ条件ではありません。
このため、eにはイの条件を入れます。
誤りやすいポイント
- %と_の意味を混同しないようにしましょう。%は0文字以上、_は1文字を表します。
- INは、指定した値の中から一致するものを探す条件です。値をすべて列挙しているので、指定されていないB始まりのコードは選べません。
- 交通機関コードを交通機関名に結び付ける条件と、バスのコードを選ぶ条件は役割が違います。前者で表同士を対応付け、後者で必要な行に絞り込みます。
FAQ
Q: LIKE 'B%'は、コードがBだけのときも一致しますか?
A: %は0文字以上の文字列を表すため、Bだけでも一致します。この問題では交通機関コードが3文字なので、実際にはBの後ろに2文字あるコードが対象になります。
A: %は0文字以上の文字列を表すため、Bだけでも一致します。この問題では交通機関コードが3文字なので、実際にはBの後ろに2文字あるコードが対象になります。
Q: LIKE 'B_'では、バスのコードを選べませんか?
A: _は1文字だけを表します。コードが3文字なら、Bとその後ろの1文字までしか条件に含められず、残る文字も含めてB始まりのコードを選ぶ条件にはなりません。
A: _は1文字だけを表します。コードが3文字なら、Bとその後ろの1文字までしか条件に含められず、残る文字も含めてB始まりのコードを選ぶ条件にはなりません。
Q: 交通機関コードが同じかどうかを調べる条件は、なぜ必要ですか?
A: 通勤費表には交通機関コードと交通費があり、交通機関表にはコードと交通機関名があります。コードを使って対応する行を結び付けることで、通勤費表の情報に交通機関名を加えて表示できます。
A: 通勤費表には交通機関コードと交通費があり、交通機関表にはコードと交通機関名があります。コードを使って対応する行を結び付けることで、通勤費表の情報に交通機関名を加えて表示できます。
関連キーワード: SQL、LIKE演算子、ワイルドカード、表結合、文字列検索
設問3:
問題文を見る 従業員の通勤圏内に新しい路線が開通することになった。この影響を確認するために、通勤経路が変わる可能性がある従業員の従業員番号を抽出することにした。同じ従業員番号は一つだけ表示する。新しい路線が影響する交通機関名は“情報都市線”と“駒込バス”であり、いずれも同名の交通機関名は他にないものとする。次のSQL文のに入れる正しい答えを、解答群の中から選べ。
SELECT 通勤費表.従業員番号
FROM 通勤費表
WHERE f
fに関する解答群
ア:通勤費表.交通機関コード = (SELECT 交通機関表.交通機関コード FROM 交通機関表 WHERE 交通機関表.交通機関名 IN ('情報都市線', '駒込バス'))
イ:通勤費表.交通機関コード IN (SELECT 交通機関表.交通機関コード FROM 交通機関表 WHERE 交通機関表.交通機関名 IN ('情報都市線', '駒込バス'))
ウ:通勤費表.交通機関コード IN (SELECT 交通機関表.交通機関コード FROM 交通機関表 WHERE 交通機関表.交通機関名 IN ('情報都市線', '駒込バス')) GROUP BY 通勤費表.交通機関コード
エ:通勤費表.交通機関コード IN (SELECT 交通機関表.交通機関コード FROM 交通機関表 WHERE 交通機関表.交通機関名 IN ('情報都市線', '駒込バス')) GROUP BY 通勤費表.従業員番号
模範解答
f:エ
解説
解答の導き方
この設問では、新しい路線の影響を受ける可能性がある従業員を探し、従業員番号を重複させずに表示する方法を考えます。
-
対象となる交通機関コードを調べます。
問題文では、影響する交通機関名が「情報都市線」と「駒込バス」とされています。図2では、交通機関名と交通機関コードは交通機関表で対応付けられています。
そこで、交通機関名がこの二つのどちらかに当てはまる行から、交通機関コードを取り出します。このように、SQL(Structured Query Language:データベースに検索や操作を指示する言語)の命令の中に、別の検索命令を置くものをサブクエリといいます。 -
取り出したコードに当てはまる通勤費表の行を探します。
通勤費表の交通機関コードが、サブクエリで得たコードのいずれかと一致する行を選びます。候補のアの「=」は、比較する値が一つの場合に使います。しかし、今回は交通機関名が二つあるため、対応するコードも複数になる可能性があります。
複数の候補の中に一致する値があるかを調べるには、INを使います。したがって、交通機関コードの条件は候補のイ・ウ・エの形になります。 -
従業員番号が重複しないようにします。
問題文には「同じ従業員番号は一つだけ表示する」とあります。図2の通勤費表では、同じ従業員番号が異なる交通機関コードの行に現れることがあります。そのため、条件に当てはまる行をそのまま表示すると、同じ従業員番号が複数回出る場合があります。
GROUP BYは、指定した項目の値が同じ行をまとめる句です。従業員番号でまとめれば、同じ従業員番号は一つにできます。したがって、GROUP BYの対象は候補のエにある「通勤費表.従業員番号」です。
候補のウは交通機関コードでまとめるため、従業員番号を一つにする目的に合いません。また、従業員番号を表示するSQLで交通機関コードだけをグループ化する形も適切ではありません。
誤りやすいポイント
- 「交通機関名が二つある」ことを見落とし、「=」を選ばないようにします。サブクエリの結果が複数になる可能性があるときは、複数の候補との一致を調べるINが適しています。
- 通勤費表の行数と、表示したい従業員の人数は同じとは限りません。同じ従業員番号が複数の行に現れる可能性があるため、重複をなくす処理が必要です。
- GROUP BYで何をまとめるかは、何を重複させたくないかで決めます。この設問で一つにしたいのは交通機関コードではなく、従業員番号です。
FAQ
Q: サブクエリが複数のコードを返すと、INはどう判定しますか?
A: 通勤費表の交通機関コードが、サブクエリの結果のどれか一つと一致すれば、その行を選びます。
A: 通勤費表の交通機関コードが、サブクエリの結果のどれか一つと一致すれば、その行を選びます。
Q: GROUP BYの代わりに、重複をなくす方法はありますか?
A: SQLには、重複行を取り除くDISTINCTという指定もあります。この設問の選択肢では、従業員番号をGROUP BYでまとめる方法が示されています。
A: SQLには、重複行を取り除くDISTINCTという指定もあります。この設問の選択肢では、従業員番号をGROUP BYでまとめる方法が示されています。
Q: 候補のウで交通機関コードごとにまとめると、なぜ目的に合わないのですか?
A: 同じ従業員番号が別々の交通機関コードに対応する行にあれば、コードごとにまとめても従業員番号は一つになりません。表示結果を一つにしたい項目そのものでまとめる必要があります。
A: 同じ従業員番号が別々の交通機関コードに対応する行にあれば、コードごとにまとめても従業員番号は一つになりません。表示結果を一つにしたい項目そのものでまとめる必要があります。
関連キーワード: SQL、サブクエリ、IN、GROUP BY、重複排除
設問4:
問題文を見る Y社では、毎年4月に交通安全講習会を開催しており、通勤に自家用車(交通機関コード“C01”)を利用している従業員には受講を義務付けている。通勤に自家用車を利用していない従業員の受講は任意である。交通安全講習会を受講した従業員は、図3に示す講習会受講表で管理している。受講していない従業員のレコードは存在しない。通勤に自家用車を利用している従業員のうち、2016年4月20日に開催された交通安全講習会を受講していない従業員の従業員番号を表示する。次のSQL文のに入れる正しい答えを、解答群の中から選べ。

SELECT 通勤費表.従業員番号
FROM 通勤費表
WHERE 通勤費表.交通機関コード = 'C01' AND g
gに関する解答群
ア:通勤費表.従業員番号 = (SELECT 講習会受講表.従業員番号 FROM 講習会受講表 WHERE 受講日 IS NULL)
イ:通勤費表.従業員番号 IN (SELECT 講習会受講表.従業員番号 FROM 講習会受講表 WHERE 受講日 = '20160420')
ウ:通勤費表.従業員番号 IN (SELECT 講習会受講表.従業員番号 FROM 講習会受講表 WHERE 受講日 IS NULL)
エ:通勤費表.従業員番号 NOT IN (SELECT 講習会受講表.従業員番号 FROM 講習会受講表 WHERE 受講日 = '20160420')
模範解答
g:エ
解説
解答の導き方
求めるのは、「通勤に自家用車を利用していて、2016年4月20日の交通安全講習会には出席していない従業員」です。条件を一つずつ整理します。
-
自家用車を利用している従業員に絞ります。
問題文では、自家用車の交通機関コードは「C01」とされています。SQL(Structured Query Language:関係データベースのデータを検索・操作するための言語)の条件「通勤費表.交通機関コード = 'C01'」によって、通勤費表から自家用車を利用している従業員を選べます。 -
指定日に受講した従業員の一覧を作ります。
講習会受講表には、受講した従業員の情報が記録されています。そこで、受講日が「20160420」の行から、従業員番号を取り出します。このように、SQL文の中で別の検索を行う部分をサブクエリといいます。 -
受講者の一覧に含まれない従業員を選びます。
問題文には「受講していない従業員のレコードは存在しない」とあります。つまり、受講していない人を講習会受講表の中から探すのではなく、指定日に受講した人の一覧から除く必要があります。
INは、ある値が一覧に含まれるかを調べる条件です。その反対に、NOT INは一覧に含まれない値を選びます。したがって、サブクエリで指定日に受講した従業員番号を取り出し、通勤費表の従業員番号がその一覧に含まれないことを条件にします。
この条件に当てはまるのは、受講者の一覧にない従業員を選ぶエです。
誤りやすいポイント
-
「受講していない人」を「受講日がNULLの人」と考える
NULLは、データが入っていないことを表す値です。しかし、問題文では受講していない従業員のレコード自体がありません。存在しない行の中から、受講日がNULLの行を探すことはできません。 -
INとNOT INを逆にする
指定日の受講者を選ぶだけならINですが、今回はその人たちを除く必要があります。そのため、NOT INを使います。 -
受講日を指定し忘れる
受講者の中でも、対象となるのは2016年4月20日の講習会に出席した人です。サブクエリには、受講日が「20160420」という条件が必要です。 -
アのように、従業員番号を1件だけ返す前提で比較する
指定日に受講した従業員は複数いる可能性があります。従業員番号の一覧との比較には、複数の値を扱えるINやNOT INを使います。
FAQ
Q: 受講していない人の従業員番号を、講習会受講表から直接取り出せないのですか?
A: 受講していない人のレコードは存在しないため、講習会受講表だけを見ても、その人を特定できません。通勤費表の従業員番号から、受講者の一覧にある番号を除く方法で求めます。
A: 受講していない人のレコードは存在しないため、講習会受講表だけを見ても、その人を特定できません。通勤費表の従業員番号から、受講者の一覧にある番号を除く方法で求めます。
Q: 受講日がNULLの行を探す方法では、なぜだめなのですか?
A: NULLは、行は存在するものの、その項目の値が入っていない状態です。今回は受講していない人の行そのものがないため、NULLを探しても受講していない人は見つかりません。
A: NULLは、行は存在するものの、その項目の値が入っていない状態です。今回は受講していない人の行そのものがないため、NULLを探しても受講していない人は見つかりません。
Q: サブクエリは何を返していますか?
A: 受講日が「20160420」である講習会受講表の行から、従業員番号の一覧を返しています。外側の検索は、その一覧に含まれない従業員番号を選びます。
A: 受講日が「20160420」である講習会受講表の行から、従業員番号の一覧を返しています。外側の検索は、その一覧に含まれない従業員番号を選びます。
関連キーワード: SQL、サブクエリ、IN述語、NOT IN述語、NULL、関係データベース



