[1] 自動車(車台番号, 車名, 会社名, 製造年) メーカー(会社名, 所在地

[1]
自動車(車台番号, 車名, 会社名, 製造年)
メーカー(会社名, 所在地)
顧客(顧客番号, 氏名, 電話番号)
販売(車台番号, 顧客番号, 販売年月日, 販売額)
【解説】
関連集合「製造」は、実体集合「メーカー」から見て1対多なので、1側(メーカー)の主キー(会社名)と、
関連集合に付けられた属性(製造年)を、多側の実体集合「自動車」に付加する。これにより、各自動車がど
のメーカーにいつ製造されたか、という情報が表現できる。
関連集合「販売」は、実体集合「自動車」
「顧客」間の多対多の関連集合なので、双方の主キー(車台番号と顧
客番号)と、関連集合に付けられた属性(販売年月日、販売額)で一つのスキーマとする。
なお、主キーの明示(下線)は必須ではない。スキーマ「販売」の主キーは、同じ顧客が同じ自動車を複数回
購入するかもしれない(買って売ったあとに買い戻す)ことを考慮した場合は、上記のように(車台番号, 顧
客番号, 販売年月日)となるが、複数回購入することがないという想定の下では、(車台番号, 顧客番号)が
主キーとなる。
[2]
(1)
スキーマ「注文」
:
注文番号
スキーマ「注文明細」
:
(注文番号, 商品番号)
【解説】
スキーマ「注文」
:
注文番号は注文ごとに付与される属性であり、候補キーとなる。
(注文年月日, 顧客番号)の組は、同一の顧客が同一年月日に複数の注文を行うこともあるという想定か
ら、候補キーとはならない。
スキーマ「注文明細」
:
試験問題に例示したように、注文番号だけでは一つの注文明細(タプル)を識別(特定)できない。
一つの注文中に同一の商品番号の明細は存在しないため、(注文番号, 商品番号)の組が候補キーとなる。
(2)
スキーマ「注文」
:
顧客番号→顧客名
スキーマ「注文明細」
:
商品番号→商品名
商品番号→単価
(3)
注文(注文番号, 注文年月日, 顧客番号)
顧客(顧客番号, 顧客名)
注文明細(注文番号, 商品番号, 数量)
商品(商品番号, 商品名, 単価)
[3]
(1)
SELECT 論文名, 掲載誌名, 発行年
FROM 教員 JOIN 論文 USING (教員 ID)
← 「FROM 教員 NATURAL JOIN 論文」 なども可
WHERE 氏名 = ’阪大太郎’
ORDER BY 発行年 DESC
(2)
SELECT COUNT(*)
FROM 教員 JOIN 部局 USING (部局 ID) JOIN 論文 USING (教員 ID)
WHERE 部局名 = ’工学研究科’ AND 発表年 = 2014
(3)
SELECT 氏名, COUNT(*)
FROM 教員 JOIN 論文 USING (教員 ID)
GROUP BY 教員 ID, 氏名
← 「教員 ID」は必要(同姓同名の教員を別に扱うため)
ORDER BY COUNT(*) DESC
※FROM 句の「JOIN」を「LEFT JOIN」としてもよい。その場合、発表論文数が 0 件の教員も出力される。
(4)
SELECT 氏名, 部局名
FROM 教員 JOIN 部局 USING (部局 ID)
WHERE 教員 ID NOT IN
(SELECT 教員 ID
FROM 論文
WHERE 発行年 = 2014)
【解説】
「1 つもない」は LEFT JOIN で実現したいところだが、以下のような SQL では外部結合後に発行年が 2014 年
のものだけが選択されてしまい、「論文名 IS NULL」が意味をなさなくなる。
SELECT 氏名, 部局名
FROM 教員 JOIN 部局 USING (部局 ID) LEFT JOIN 論文 USING (教員 ID)
WHERE 発行年 = 2014 AND 論文名 IS NULL
もし LEFT JOIN を使いたいなら、(講義では紹介していないが)FROM 句にサブクエリを用いる方法(インライ
ンビューなどと呼ばれる)を用いれば可能である。
SELECT 氏名, 部局名
FROM 教員 JOIN 部局 USING (部局 ID)
LEFT JOIN (SELECT * FROM 論文 WHERE 発行年 = 2014) 論文 2014
WHERE 論文名 IS NULL
これは、
「2014 年発行の論文」
(論文 2014 という別名を付けている)を外部結合の対象となるので、結合対象
がない(2014 年発行の論文がない)教員のタプルには、論文種別、論文名、掲載誌名、発行年に NULL が入っ
たタプルが結合される。従って、「論文名 IS NULL」で「2014 年の発表論文数が 1 つもない」という条件を表
現できる。
[4]
(a) ハッシュファイル
(b) 二次索引
(c) 合理的
(d) 実行プラン
(e) ログ
(f) no-undo/redo
(g) undo/no-redo
(h) undo/redo
(i) 原子性 / 不可分性
(j) 耐久性 / 永続性
[5]
A
T1
T3
C
B
T2
サイクルが存在するので競合直列可能ではない。
【解説】
アクセス対象のデータ項目ごとに抜き出してみる。
A : R1(A) W1(A) R3(A) W3(A) ・・・ R1(A)と W3(A)、W1(A)と R3(A)/W3(A) が競合
⇒ T1→T3
B : R2(B) W2(B) R1(B) W1(B) ・・・ R2(B)と W1(B)、W2(B)と R1(B)/W1(B) が競合
⇒ T2→T1
C : R3(C) W2(C) ・・・ R3(C)と W2(C) が競合
⇒ T3→T2
[6]
(a)
33 52
17 20
12
18
38 44
21
35
41
60
46 48
55
69
18 を追加したいノードには「12,17」で一杯なので、ノードを分割し、中央の 17 を親ノードに追加する。
(b)
44
33
20
12 17
21
52
48
38
35
41
46
60
50
55
69
50 を追加したいノードは「46,48」で一杯なので、ノードを分割し、中央の 48 を親ノードに追加する。
親ノードは「38,44」で一杯なので、ノードを分割し、中央の 44 を親ノード(ルートノード)に追加する。
ルートノードも「33,52」で一杯なので、ノードを分割し、中央の 44 を新たに追加した親ノード(ルートノー
ド)に追加する。
(c)
33 52
17
12
20
38 44
35
41
60
46 48
55
69
21 を削除するとノード内のレコード数が半数を下回るため、親を共有する左か右のノード(ここでは左)のレ
コード数をチェックする。左のノードのレコード数が(半数+1)以上なので、親ノードの 20 を含めて再配分す
る。
(d)
33 44
20
12 17
21
38
35
55
41
46 48
60 69
削除する 52 は非リーフノードなので、右の部分木の最も左のリーフノードの先頭レコード(55)を 52 の位置
に移動させる。
すると 55 が入っていたノード内のレコード数が半数を下回るため、親を共有する左か右のノード(ここでは
右)のレコード数をチェックする。右のノードのレコード数がちょうど半数(69 だけ)なので、親ノードの 60
を含めて一つのノードに融合する。
すると 60 が入っていたノード内のレコード数が半数を下回るため、親を共有する左か右のノード(ここでは
左)のレコード数をチェックする。左のノードのレコード数が(半数+1)以上なので、親ノードの 55 を含めて
再配分する。
33 48
20
12 17
21
38 44
35
41
60
46
55
69
削除する 52 の右の部分木の最も左のリーフノードの先頭レコードではなく、左の部分木の最も右のリーフノ
ードの末尾のレコード(48)を 52 の位置に移動させた場合は上図のようになる。これも正解とする。
(面白く
ないが)
[7]
3行以上書いていればよしとする。