web-dev-qa-db-ja.com

SQLをリレーショナル代数/微積分に変換する

スキーマを設計し、いくつかのSQLクエリを生成しました。 PostgreSQLを使用しています。

例えば:

CREATE TABLE train 
(
  train_code SERIAL PRIMARY KEY,
  name TEXT NOT NULL
); 

CREATE TABLE journey 
(
  journey_id SERIAL PRIMARY KEY, 
  int INTEGER,
  train_code REFERENCES train(train_code)
); 

CREATE TABLE price 
(
  journey_id REFERENCES journey(journey_id),
  price INTEGER
); 

価格が50ドル以上のtrain_code NYCまたはSFOから始まるすべての列車名を教えてください。 (価格表がすでに$にあると想定します)。

SELECT train.name
JOIN   train
JOIN   journey on train.train_code = journey.train_code
JOIN   price on price.journey_id = journey.journey_id 
WHERE  price.price >= 50 
AND    journey.train_code IN ('NYC', 'SFO') 
AND    journey.int = 1 -- (first train of the journey)

これを関係代数や微積分クエリに変換する方法がわかりません。私はいくつかのコンバーターを見てきました。 http://dbis-uibk.github.io/relax/calc.htm ただし、この計算機では、たとえば「結合」や「結合」は許可されていません。

3
Dino Abraham

SQLにはいくつかの「間違い」がありますが、リレーショナル代数に変換する前に対処する必要があります。

  1. SQLにFROMがありません。 JOINingから始めるべきではありません。
  2. _train_code_はテキストであると想定しているようですが、それを整数として定義しています。
  3. テーブル定義では、typeテーブルの_train_code_に対してjourneyを定義せず、priceテーブルの_journey_id_に対しても定義しません。
  4. 使用しているツールはSERIAL(標準SQLではありません)を理解していません。使用しないでください。代わりにINTEGERを使用してください。

したがって、テーブル定義は次のようになります。

_CREATE TABLE train 
(
  train_code TEXT PRIMARY KEY,
  name TEXT NOT NULL
); 

CREATE TABLE journey 
(
  journey_id INTEGER PRIMARY KEY, 
  int INTEGER,
  train_code TEXT REFERENCES train (train_code)
); 

CREATE TABLE price 
(
  journey_id INTEGER REFERENCES journey (journey_id),
  price INTEGER
); 
_

これはRelaXによって次のように翻訳されます。

_group: joanolo (imported from SQL)

train = {
    train_code:string, name:string
}

journey = {
    journey_id:number, int:number, train_code:string
}

price = {
    journey_id:number, price:number
}
_

クエリ側では、FROMを追加する必要があり、x IN (a, b)を_(x = a OR x = b)_に変更するだけです。次のクエリが作成されます。

_SELECT 
    train.name
FROM   
    train
    JOIN  journey on train.train_code = journey.train_code
    JOIN  price on price.journey_id = journey.journey_id 
WHERE  
    price.price >= 50 
    AND (journey.train_code = 'NYC' OR journey.train_code = 'SFO') 
    AND  journey.int = 1
_

この形式はRelaXによって理解され、探している結果を提供します。

πtrain.nameσprice.price≥50および(journey.train_code = 'NYC'またはjourney.train_code = 'SFO')およびjourney.int = 1 train⨝train.train_code = journey.train_codejourney⨝price.journey_id = journey .journey_id価格

enter image description here

つまり、SELECT句の条件でフィルタリングするWHERE 1つのprojection (π)と同等の1つのselection (σ)と、2つのjoins (⨝) SQL JOINと同等です。

2
joanolo