「Tutorial D で関係変数の定義と代入」 のつづき
「データベース実践講義」 における “5.2 オリジナル演算子” (pp.92-99) の練習。
「SQL の相関サブクエリ (2)」 で利用したデータベースと同じものを使う。
Tutorial D での定義は以下通り。
削除するときはこちらより。
制限
特定の条件に一致するタプルを含む関係を返す。例えば、男性を取得するには、
persons where gender = 1
SQL の WHERE 句に相当し、同じキーワード where を使うので覚えやすい。
射影
特定の属性を含む関係を返す。人の名前と年齢を取得するには、
persons { name, age }
SQL の SELECT 句に相当する。こちらは位置も表現も異なる。
SQL との違いは、以下を評価するとハッキリとする。
persons { gender }
リレーショナル代数で 「関係」 が返されるわけだから、重複はない。 SQL では SELECT 句で DISTINCT を指定することに相当。
結合
「人」 と 「割当て」 を結合する。 SQL の自然結合に相当。
persons rename(id as p_id) join assignments
ただし、結合には同じ属性名が使われるので、結合前に属性名を変更するため rename 演算子を利用する。
ここでは assignments で 「人」 を示すための属性として p_id を利用しているので、上記では persons の属性 id を p_id に変更している。
次に 「人」 「割当て」 「グループ」 の 3 つを結合し、「人の名前、グループ名、日付」 を表示する。
(persons rename(id as p_id) join assignments join groups rename(id as g_id, name as g_name)) {name, g_name, date}
複数の属性名を一気に変更する場合は、rename 演算子において prefix を利用する。
(persons rename(prefix "" as "p_") join assignments join groups rename(prefix "" as "g_")) {p_name, g_name, date}
結合は、join { A, B, C … } のように書くことができる。
join { persons rename(prefix "" as "p_") , assignments , groups rename(prefix "" as "g_")} {p_name, g_name, date}
交わり
「人」 の属性 id と 「割当て」の属性 p_id の交わりを求める。
(persons rename(id as p_id)) {p_id} intersect assignments {p_id}
交わりは、属性が全て同じ関係の結合と見なせるので、join を使っても書ける。
(persons rename(id as p_id)) {p_id} join assignments {p_id}
デカルト積
「人」の名前 と 「グループ」名 のすべての組み合わせを求めたい。
デカルト積は、共通属性がない関係の結合と見なせるので、結合したい関係の属性名が重ならないように rename 演算子を用いる。このとき、prefix を利用すると便利。
(persons rename(prefix "" as "p_") join groups rename(prefix "" as "g_")) {p_name, g_name}
SQL では FROM 句にテーブル名を並べることに相当。
半結合
「グループ」 に 「割当て」 られている 「人」 を抽出したい。
persons semijoin assignments
データベース実践講義 (p94) によると、
(半結合についてこれまでに聞いたことがないかもしれないが、実がとても重要な演算子である)。定義は次の通り。 r と s の半結合は、 r と s の結合であり、結果は r の属性に射影される。
semijoin の代わりに matching と書くこともできる。こちらの方が言葉としては理解しやすいかな。
SQL では exists 述語を利用して記述できる。
和
「人」 と 「人」 の和。
(persons where id = 1) union relation {tuple {id 100, name "Gonzou", gender 1, age 100}}
直和
共通のタプルがあった場合に、エラーが出力される和も用意されている。
(persons where id <= 3) d_union (persons where id >= 3)
この場合、「人」 の id が 3 の人が共通してるのでエラーとなる。
差
特定の 「人」 を取り除きたい場合。
persons { name } minus relation { tuple { name "Hanko" }
, tuple { name "Jirou" }
, tuple { name "Sadayo" }}
半差
先ほどの 「半結合」 とは対照的な 「半差」。 SQL では not exists 述語に相当する演算子。
persons rename(id as p_id) semiminus assignments
差は、属性が全て共通している関係の半差と見なせる。
persons { name } semiminus relation { tuple { name "Hanko"} , tuple { name "Jirou"} , tuple {name "Sadayo" }}
その他
「商」 はどうやって書いたらいいんだろう。。 (+_+)
「Tutorial D の拡張と要約 - 値の計算と集約」へつづく
0コメント:
コメントを投稿