web-dev-qa-db-fra.com

Convertir SQL en algèbre / calcul relationnelle

J'ai conçu un schéma et j'ai généré quelques requêtes SQL. J'utilise PostgreSQL.

Par exemple:

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
); 

Donnez-moi tous les noms de train qui commencent à partir de Train_Code NYC ou SFO au prix de 50 $ ou plus. (Supposons que la table de prix est déjà en dollars).

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)

Je ne sais pas comment convertir cela en une algèbre relationnelle et/ou une requête de calcul de calcul. J'ai regardé quelques convertisseurs par ex. http://dbis-uibk.github.io/relax/calc.htm Mais dans cette calculatrice 'Rejoindre' par exemple et 'in' n'est pas autorisé.

3
Dino Abraham

Vous avez un certain nombre de "erreurs" dans votre SQL, qui devraient être adressées avant de le traduire en algèbre relationnelle.

  1. Vous n'avez pas de FROM dans votre SQL. Vous ne devriez pas commencer par JOINing.
  2. Vous semblez supposer que train_code Est un texte, mais vous le définissez comme un entier.
  3. Votre table Définitions Ne définissez pas un type pour train_code Dans la table journey _, ni pour journey_id Dans le price un.
  4. L'outil que vous utilisez ne comprend pas SERIAL (qui n'est pas standard SQL). Juste ne l'utilise pas. Utilisez INTEGER à la place.

Donc, vos définitions de table doivent simplement être:

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
); 

Ceci est traduit par 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
}

Sur le côté de la requête, vous devez ajouter un FROM et vous venez de changer x IN (a, b) sur (x = a OR x = b). Vous finirez par avoir la requête suivante:

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

Ce format est compris par RelaX et vous donnera le résultat que vous recherchez:

π Train.name σ Prix.Price ≥ 50 et (Voyage.train_code = 'NYC' ou Journey.train_code = 'SFO') et Journey.int = 1 train ⨝ Train.Train_Code = Voyage.train_Code voyage ⨝ Prix.Journey_id = .journey_id Price

enter image description here

C'est-à-dire que vous avez une projection (π), équivalent à votre SELECT One selection (σ) qui filtre avec la condition dans votre clause WHERE et deux joins (⨝) qui sont équivalents à SQL JOIN.

2
joanolo