3

リレーショナル代数に変換したい SQL クエリがいくつか書かれています。ただし、一部のクエリは集計演算子を使用しており、それらを変換する方法がわかりません。特に、COUNT および GROUP BY.. HAVING 演算子を使用します。

スキーマは次のとおりです。

セーラー( sid , sname, rating) リザーブ( sid , bid , price) Boats( bid , bname)

これは私が行っていることの例です: 正確に 2 人の船員によって予約されたすべてのボートの入札と名前を見つけます.

SELECT B.bid, B.bname
FROM Boats B, Reserves R
WHERE B.bid = R.bid
GROUP BY R.bid
HAVING 2 = (SELECT COUNT(*)
FROM Reserves R2
WHERE R2.bid = B.bid);

可能な関係代数演算: 選択、射影、結合、条件付き結合、名前変更、結合、交差、クロス積、除算

4

3 に答える 3

5

これは半分だけの答えです...

「2 人以上の船員によって予約されたボート」という関係は、条件付き結合と射影を使用して見つけることができます。これらは両方とも、許可された操作のセットに含まれています。

SELECT DISTINCT R1.bid
  FROM Reserves AS R1 
       JOIN Reserves AS R2
          ON R1.bid = R2.bid
             AND R1.sid < R2.sid;

「3 人以上の船員によって予約されたボート」という関係は、条件付き結合 (2 回) と射影を使用して見つけることができます。これらは両方とも、許可された操作のセットに含まれています。

SELECT DISTINCT R1.bid
  FROM Reserves AS R1
       JOIN Reserves AS R2
          ON R1.bid = R2.bid
             AND R1.sid < R2.sid
       JOIN Reserves AS R3
          ON R1.bid = R3.bid
          AND R2.sid < R3.sid;

EXCEPTたとえば、標準 SQL でマイナス演算子がある場合:

SELECT DISTINCT R1.bid
  FROM Reserves AS R1 
       JOIN Reserves AS R2
          ON R1.bid = R2.bid
             AND R1.sid < R2.sid
EXCEPT
SELECT DISTINCT R1.bid
  FROM Reserves AS R1
       JOIN Reserves AS R2
          ON R1.bid = R2.bid
             AND R1.sid < R2.sid
       JOIN Reserves AS R3
          ON R1.bid = R3.bid
          AND R2.sid < R3.sid;

制限 ( SQL の場合WHERE) と準差分 (別名antijoin ) 演算子 ( NOT INSQL の場合) がある場合:

SELECT DISTINCT R1.bid
  FROM Reserves AS R1 
       JOIN Reserves AS R2
          ON R1.bid = R2.bid
             AND R1.sid < R2.sid
 WHERE R1.bid NOT IN (
                      SELECT DISTINCT R1.bid
                        FROM Reserves AS R1
                             JOIN Reserves AS R2
                                ON R1.bid = R2.bid
                                   AND R1.sid < R2.sid
                             JOIN Reserves AS R3
                                ON R1.bid = R3.bid
                                AND R2.sid < R3.sid
                     );

...しかし、許可された操作のセットには、制限、半差、またはマイナスが含まれていません:(

于 2011-09-30T10:11:44.067 に答える
4

「リレーショナル代数に関する章のある本を読んでいたのですが、それらの集合関数についてはまったく言及されていませんでした」.

関係代数に関する文献は、通常、関係を閉じた代数の一部に限定されます。代数の演算子のいずれもがそのセットのメンバーではない型の値を返さない場合、代数は型のセットに対して閉じられています (私はおそらく少しずさんな表現をしていますが、主なアイデアは正しいです)。型の代数は閉じられています。

あなたが持っている (または本で検討したい) のがすべての関係型のセットであり、代数の扱いを書きたい場合、整数 (COUNT) または浮動小数 ( HARMONICMEAN)、または日付 (MIN(<date column>))、または代数の「閉じた」プロパティを壊すことなく、同様の種類のもの。

そのような集計操作が役に立たないというわけではありません (もちろんそうではありません)。通常、主な目的が JOIN、PROJECT、RESTRICT などを説明することであるコンテキストでは、それらは正確には関係ありません。

編集

GROUP BY ... HAVINGに関する補足回答。この SQL 構造は、代数の同等物に関しては自明ではないことに正しく気付きました。その要点は、あなたが言及した代数演算子のセットには、そのようなものを達成するために必要な演算子がなく、この演算子がGROUPであるということです。GROUP は入力リレーションを取り、属性の 1 つがリレーション値である出力リレーションを生成します。

たとえば、GROUP ( RESERVES , SAILORS_AND_THEIR_BID ( SID , PRICE ) ) は、属性 BID および SAILORS_AND_THEIR_BID を持つ次数 2 の関係を生成します。後者の属性は関係値であるため、式 COUNT(SAILORS_AND_THEIR_BID) は、この関係に適用される RESTRICT 条件のコンテキストで有効になり、次のように記述できます ( GROUP ( RESERVES , SAILORS_AND_THEIR_BID ( SID , PRICE ) ) ) WHERE COUNT (SAILORS_AND_THEIR_BID) = 2.

于 2011-10-01T19:46:00.637 に答える
1

onedaywhenの答えに基づいて構築:

はい、集合差演算子の欠如は害を及ぼします。絶対に許すべきです。ただし、集合の補数と交差で集合の差を表すことができます。

B - A = B ∩ A'

つまり、B と A の差は、実際には B と A の補数の交差です。許可された演算子として交点があり、リレーションの適切な補数は醜いものですが、R に対する R1 ⊆ R の補数 (つまり、R1 にない R のもの) は結合で簡単に見つけることができます。 :

SELECT DISTINCT R0.x
FROM R as R1
JOIN R as R0 ON R1.x<>R0.x
WHERE R1.x=val

のRに対する補数です

SELECT DISTINCT R.x FROM R WHERE R.x=val

だから、ここになぞなぞの解決策があると思います.2人以上の男が予約したすべてのボートを取得するのは簡単です:予約表にあるすべてのボートを選択し、結果のデカルト積をそれ自体で取り、次に選択します異なる船員 1 と船員 2 を持つ各行。扱いにくい関係代数の表記法で、彼らは私に教えてくれました:

π( R.bid ) (
   σ( R.bid=R2.bid and R.sid<R2.sid )( R x ρ(R, R2) ) 
)

(ここで、π は射影演算子、σ は選択演算子、ρ は名前変更演算子です)

これにより、2 人以上が予約したすべてのボートの ID が取得されます。今、私は 2 人以下の男性によって予約されたすべてのボートを手に入れるつもりです。これを行うには、3 人以上の男が予約しているすべてのボートを選択し、そのセットに存在しない元のテーブルからすべての行を選択して、セットの補数を取得します。きれいではありませんが、次のようになります。

 π(R.bid)(σ(R.bid<>R1.bid)(
    π(R.bid)(R)
      x
    π(R1.bid) (
        σ( R1.bid=R2.bid and R2.bid=R3.bid and R1.sid<R2.sid and R2.sid<R3.sid )( ρ(R, R1) x ρ(R, R2) x ρ(R, R3) )
     )
  ))

ご覧のとおり、プロパティを持つすべての行を選択し、次にこれらではない元のテーブルからすべての行を選択して、プロパティを持たないすべての行をネットします。ここでは、3 人によって予約されていないすべてのボートを意味します2人以下で予約したボート。

正確に 2 人の男が予約しているボートを取得するには、これを複数の男が予約したボートのセットと単純に交差させます。

π( R.bid ) (
   σ( R.bid=R2.bid and R.sid<R2.sid )( R x ρ(R, R2) ) 
) ∩ π( R.bid ) (
    σ(R.bid<>R1.bid)(
       π(R.bid)(R)
         x
       π(R1.bid) (
           σ( R1.bid=R2.bid and R2.bid=R3.bid and R1.sid<R2.sid and R2.sid<R3.sid )( ρ(R, R1) x ρ(R, R2) x ρ(R, R3) )
        )
     )
 )

うーん。痛いほど醜いです。もっといい表記を知りたいです。

SQL 的には、次のようになると思います。

(SELECT DISTINCT R1.bid
  FROM Reserves AS R1 
    JOIN Reserves AS R2 ON R1.bid = R2.bid AND R1.sid < R2.sid
) INTERSECT (
SELECT DISTINCT R.bid
  FROM Reserves AS R1
    JOIN Reserves AS R2 ON R1.bid = R2.bid AND R1.sid < R2.sid
    JOIN Reserves AS R3 ON R1.bid = R3.bid AND R2.sid < R3.sid
    JOIN Reserves AS R ON R.bid<>R1.bid
)

これはまさに onedaywhen の解であることに注意してください。

于 2011-10-13T00:07:07.887 に答える