© Your Copyright
Le calcul relationnel est une notation logique, où l’on exprimera les requêtes par la formulation de restrictions logiques que les éléments (tuples) retenus dans la réponse à la requête devront satisfaire.
On distingue :
Calcul Relationnel de Domaine (DRC) : les variables sont les attributs des n-uplets (tuples).
- exemple : \(x \in Personnes.nom\)
cette représentation de requêtes est issue des travaux sur le langage QBE (IBM)
calcul relationnel de tuples (TRC): les variables sont les éléments (n-uplets).
- exemple : \(x \in Personnes\)
cette représentation de requêtes est issue des travaux sur le langage QUEL (INGRES)
Le DRC est un langage d’interrogation de données formel permettant d’exprimer des questions à partir de formules bien formées dont chaque variable est interprétée comme variant sur le domaine d’un argument d’un prédicat.
Une question en calcul relationnel de domaine s’écrit sous la forme :
- \(\{(x,y,...) \; \mid \; F(x,y, ...)\}\)
produits(id_prod, nom, quantite, couleur)
nom
et couleur
de tous les produits
:
- \(R=\{(n,c) \mid produits(-,nom:n,-,couleur:c)\}\)
nom
et quantite
en stock des produits
de couleur
rouge
:
- \(R=\{(n,q) \mid produits(-,nom:n,quantite:q,couleur="rouge")\}\)
Le TRC est un langage d’interrogation de données formel permettant d’exprimer des questions à partir de formules bien formées dont les variables sont interprétées comme variant sur les éléments (n-uplets) d’une table.
Une question en calcul relationnel de tuples s’écrit sous la forme :
- \(\{(t_1.x,t_1.y,t_2.u,t_2.v,...) \; \mid \; F(t_1,t_2 ....) \}\)
ou bien :
- \(\{(t.x,t.y,t_2.u,t_2.v,...) \; \mid \; t_1 \in T_1 \land t_2 \in T_2 \; ... \}\)
où :
- \(F\) : est une formule logique sur des éléments (tuples) des ensembles \(T_1,T_2,...\)
- \((t_1.x,t_1.y,t_2.u,t_2.v...)\) : attributs des n-uplets (tuples) des ensembles \(T_1,T_2,...\)
produits(id_prod, nom, quantite, couleur)
nom
et couleur
de tous les produits
:
- \(R=\{(p.nom,p.couleur) \mid produits(p)\}\)
ou :
- \(R=\{(p.nom,p.couleur) \mid p \in produits\}\)
nom
et quantite
en stock des produits
de couleur
"rouge"
:
- \(R=\{(p.nom,p.quantite) \mid produits(p) \land p.couleur="rouge"\}\)
ou :
- \(R=\{(p.nom,p.quantite) \mid p \in produits \land p.couleur="rouge"\}\)
Toute requête sur une base de données peut être exprimée par une formule de logique du premier ordre en calcul relationnel.
Les opérateurs de l’algèbre relationnelle qui seront utilisés pour formuler des requêtes sur une base de données peuvent être formalisés en calcul relationnel :
Projection : réduire le nombre d’attributs (\(a_1,...,a_n\)) sur les éléments d’un ensemble (\(E\))
- \(\Pi_{(a_1,...,a_n)}(E)=\{ (e.a_1,....,e.a_n) \; | \; e \in E \}\)
Restriction : récupérer les éléments (\(e\)) d’un ensemble (\(E\)) qui satisfont un critère de restriction \([p(e)]\)
- \(\sigma_{[p(e)]}(E)=\{ e \; | \; e \in E \land p(e) \}\)
Produit cartésien : mettre en relation chaque élément de l’ensemble \(S\) avec tous les éléments de l’ensemble \(T\)
- \(\times(S,T)=\{ (s,t) \; | \; s \in S \land t \in T \}\)
Union : créer l’ensemble contenant les éléments qui sont dans l’ensemble \(S\) et dans l’ensemble \(T\)
- \(\cup(S,T)=\{ r \; | \; r \in \Pi_{(s_1,...,s_n)}(S) \lor r \in \Pi_{(t_1,...,t_n)}(T) \}\)
Les éléments des deux ensembles ont le même nombre d’attributs définis sur le même domaine.
Différence : créer l’ensemble contenant les éléments de l’ensemble \(S\) qui ne sont pas dans l’ensemble \(T\)
- \(\setminus(S,T)=\{ r \; | \; r \in \Pi_{(s_1,...,s_n)}(S) \land r \notin \Pi_{(t_1,...,t_n)}(T) \}\)
Les éléments des deux ensembles ont le même nombre d’attributs définis sur le même domaine.
Intersection : créer l’ensemble contenant uniquement les éléments de l’ensemble \(S\) qui sont aussi dans l’ensemble \(T\)
- \(\cap(S,T)=\{ r \; | \; r \in \Pi_{(s_1,...,s_n)}(S) \land r \in \Pi_{(t_1,...,t_n)}(T) \}\)
Les éléments des deux ensembles ont le même nombre d’attributs définis sur le même domaine.
Jointure : mettre en relation les éléments \((s,t)\) des ensembles \((S,T)\) s’ils satisfont un critère de jointure \([p(s,t)]\)
- \(\Join_{[p(s,t)]}(S,T)=\{ (s,t) \; | \; s \in S \land t \in T \land p(s,t) \}\)
Division relationnelle : récupérer les éléments (\(r\)) des éléments (\(s=(r,t)\)) de l’ensemble \(S\) qui sont en relation avec tous les éléments (\(t\)) de l’ensemble \(T\)
- \(\div(S,T)=\{r \; | \; \forall t \in T, (r,t) \in S \}\)
où l’ensemble des attributs de \(T\) est un sous-ensemble de l’ensemble des attributs de \(S\) (\(attr(T) \subset attr(S)\))
On formulera ici les recherches d’information en calcul relationnel sur le modèle de données des « bars qui servent des bières ».
On pourra vérifier le résultat sur une base de données SQLite en formulant les requêtes SQL.
bar
), est localisé dans un pays (pays
),biere
), une couleur (couleur
) et un pays d’origine de fabrication (origine
),stock
) de bières servies dans les bars.
CREATE TABLE bars (
id_bar INTEGER NOT NULL PRIMARY KEY,
bar VARCHAR(20),
pays VARCHAR(20)
);
CREATE TABLE bieres (
id_biere INTEGER NOT NULL PRIMARY KEY,
biere VARCHAR(20),
couleur VARCHAR(10),
origine VARCHAR(20)
);
CREATE TABLE services (
id_bar INTEGER NOT NULL,
id_biere INTEGER NOT NULL,
stock SMALLINT,
PRIMARY KEY (id_bar, id_biere),
FOREIGN KEY (id_bar) REFERENCES bars,
FOREIGN KEY (id_biere) REFERENCES bieres
);
Calcul relationnel de domaine :
\(R=\{ (b,c) \; | \; bieres(-,biere:b,couleur:c,-) \}\)
Calcul relationnel de n-uplets :
\(R=\{ (b.biere,b.couleur) \; | \; b \in bieres \}\)
SQL :
SELECT couleur,biere FROM bieres;
Calcul relationnel de domaine :
\(R=\{ (id,b,c,o) \; | \; bieres(id\_biere:id,biere:b,couleur:c,origine="France":o) \}\)
Calcul relationnel de n-uplets :
\(R=\{ b \; | \; b \in bieres \land origine="France" \}\)
SQL :
SELECT * FROM bieres WHERE origine='France';
Calcul relationnel de domaine :
\(R= \{ (id\_ba,ba,p,id\_bi,bi,c,o) \; | \; bars(id\_bar:id\_ba,bar:ba,pays:p) \land bieres(id\_biere:id\_bi,biere:bi,couleur:c,origine:o) \}\)
Calcul relationnel de n-uplets :
\(R= \{ (ba,bi) \; | \; ba \in bars \land bi \in bieres \}\)
SQL :
SELECT * FROM bars, bieres;
-- ou
SELECT * FROM bars CROSS JOIN bieres;
Calcul relationnel de domaine :
\(R= \{ nom \; | \; bars(-,-,pays:nom) \lor bieres(-,-,-,origine:nom) \}\)
Calcul relationnel de n-uplets :
\(R=\{ nom \; | \; (b.pays:nom, b \in bars) \lor (b.origine:nom, b \in bieres) \}\)
SQL :
SELECT pays AS nom FROM bars
UNION
SELECT origine AS nom FROM bieres;
Calcul relationnel de domaine :
\(R= \{ nom \; | bars(-,-,pays:nom) \land \neg bieres(-,-,-,origine:nom) \}\)
Calcul relationnel de n-uplets :
\(R=\{ nom \; | \; (b.pays:nom, b \in bars) \land \neg (b.origine:nom, b \in bieres)\}\)
SQL :
(SELECT pays AS nom FROM bars)
EXCEPT
(SELECT origine AS nom FROM bieres);
Calcul relationnel de domaine :
\(R= \{ nom \; | \; bars(-,-,pays:nom) \land bieres(-,-,-,origine:nom) \}\)
Calcul relationnel de n-uplets :
\(R=\{ (nom \; | \; (b.pays:nom, b \in bars) \land (b.origine:nom, b \in bieres) \}\)
SQL :
(SELECT pays AS nom FROM bars)
INTERSECT
(SELECT origine AS nom FROM bieres);
Calcul relationnel de domaine :
\(R= \{ nom \; | \; bars(-,-,pays:nom) \land \exists \; o \; bieres(-,-,-,origine:o=nom) \}\)
Calcul relationnel de n-uplets :
\(R=\{ nom \; | \; (ba.pays:nom, ba \in bars) \land (bi.origine:nom, bi \in bieres) \land ba.pays=bi.origine\}\)
SQL :
SELECT pays AS nom FROM bars INNER JOIN bieres ON(pays=origine);
-- ou
SELECT pays AS nom FROM bars,bieres WHERE pays=origine;
Calcul relationnel de domaine :
\(R=\{nom \; | \; bars(id\_bar:id_\_ba,bar:nom,-,-) \land \; \forall \; id\_bi \; bieres(id\_biere:id\_bi,-,-,-), services(id\_ba,id\_bi,-)) \}\)
Calcul relationnel de n-uplets :
\(R=\{ba.bar \; | ba \in bars \land \; (\forall bi \in bieres \; , \; (ba,bi) \in services) \}\)
SQL :
L’opérateur n’existe pas en SQL mais peut être exprimé par une double négation (NOT EXISTS)
« Trouver les bars tel qu” il n’existe pas de bière pour laquelle il n’existe pas de service associant ce bar et cette bière »
SELECT *
FROM bars ba
WHERE NOT EXISTS( SELECT *
FROM bieres bi
WHERE NOT EXISTS( SELECT *
FROM services s
WHERE s.id_bar=ba.id_bar
AND s.id_biere=bi.id_biere
)
);
NB : pour plus d’information sur la division relationnelle on pourra se reporter à la section correspondante de ce chapitre.
NB: la notation : attribut:alias
(ex : pays:nom) symbolise un alias
(ex: nom) d”attribut
(ex: pays) .
Table « bars » | Table « bieres » | Table « services » | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
On formulera ici les recherches d’information en calcul relationnel sur le modèle de données du « Tournoi des six nations ».
On pourra vérifier le résultat sur une base de données SQLite en formulant les requêtes SQL.
Faire le diagramme de classes correspondant au modèle de données suivant :
une équipe (
equipe
) a un nom (nom_equipe
), fait partie d’une nation (pays
) et a un entraîneur (coach
)les joueurs (
joueurs
) font partie d’une équipe (id_equipe
) ont un nom et un prénom (nom,prenom
), jouent à un poste précis (position
) peuvent être de différentes nationalités (nationalite
).Pour chaque joueur on connaît sa date de naissance, leur taille et leur poids (
naissance,taille,poids
).un (
match
) concerne deux équipes (id_locaux,id_visiteurs
), a lieu un jour à un horaire précis (jour,horaire
) sur le stade de l’équipe qui accueille (stade
)Chaque match donnera lieu à un score pour l’équipe qui reçoit (
locaux_score
) et celle qui joue à l’extérieurvisiteurs_score
).On notera aussi l’affluence du nombre de spectateurs (
spectateurs
) le jour du match.Les matchs donnent lieu à des (
selections
) de joueurs.A chaque match (
id_match
) on associera les joueurs (id_joueur
) sélectionnés, le nombre d’essais (essais
), de transformations (transformations
) et de pénalités qu’ils ont marqués (penalites
).
Créer les tables correspondant à ce modèle de données :
CREATE TABLE equipes (
id_equipe CHAR(3) PRIMARY KEY,
nom_equipe TEXT,
pays TEXT,
coach TEXT
);
CREATE TABLE joueurs (
id_joueur INTEGER PRIMARY KEY AUTOINCREMENT,
id_equipe CHAR(3),
nom TEXT,
prenom TEXT,
position TEXT,
nationalite TEXT,
naissance DATE,
taille FLOAT CHECK (1 < taille and taille < 3) DEFAULT 1.80,
poids FLOAT CHECK (50 < poids and poids < 150) DEFAULT 80,
FOREIGN KEY(id_equipe) REFERENCES equipes(id_equipe)
);
CREATE TABLE matchs (
id_match INTEGER PRIMARY KEY AUTOINCREMENT,
id_locaux CHAR(3),
id_visiteurs CHAR(3),
jour DATE,
horaire TIME,
locaux_score INTEGER,
visiteurs_score INTEGER,
stade TEXT,
spectateurs INTEGER,
FOREIGN KEY(id_locaux) REFERENCES equipes(id_equipe),
FOREIGN KEY(id_visiteurs) REFERENCES equipes(id_equipe)
);
CREATE TABLE selections (
id_joueur INTEGER NOT NULL,
id_match INTEGER NOT NULL,
essais SMALLINT DEFAULT 0,
transformations SMALLINT DEFAULT 0,
penalites SMALLINT DEFAULT 0,
PRIMARY KEY(id_joueur,id_match),
FOREIGN KEY(id_match) REFERENCES matchs(id_match),
FOREIGN KEY(id_joueur) REFERENCES joueurs(id_joueur)
);
Calcul relationnel de domaine :
\(R=\{ (n,p) \; | \; joueurs(-,-,nom:n,prenom:p,-,-,-,-,-) \}\)
Calcul relationnel de n-uplets :
\(R=\{ (j.nom,j.prenom) \; | \; j \in joueurs \}\)
SQL :
SELECT nom,prenom FROM joueurs;
Calcul relationnel de domaine :
\(R=\{ (id\_j,id\_equipe,n,pr,pos,nat,nai,t,poi) \; |\)
\(\qquad \quad joueurs(id\_joueur:id_j,id\_equipe='FRA',nom:n,prenom:pr,position:pos,\)
\(\qquad \qquad \qquad \qquad nationalite:nat,naissance:nai,taille:t,poids:poi) \}\)
Calcul relationnel de n-uplets :
\(\displaystyle R=\{ j \; | \; j \in joueurs \land j.id\_equipe="FRA" \}\)
SQL :
SELECT * FROM joueurs WHERE id_equipe='FRA';
Calcul relationnel de domaine :
\(R= \{ (id\_eq,eq,p,c,id\_j,id\_e,n,pr,pos,nat,nai,t,poi) \; |\)
\(\qquad \quad equipes(id\_equipe:id\_eq,nom\_equipe:eq,pays:p,coach:c) \land\)
\(\qquad \quad joueurs(id\_joueur:id_j,id\_e:id\_equipe:id_e,nom:n,prenom:pr,position:pos,nationalite:nat,naissance:nai,taille:t,poids:poi) \}\)
Calcul relationnel de n-uplets :
\(R = \{ (e,j) \; | \; e \in equipes \land j \in joueurs \}\)
SQL :
SELECT * FROM equipes, joueurs;
-- ou
SELECT * FROM equipes CROSS JOIN joueurs;
Calcul relationnel de domaine :
\(R=\{ nom \; | \; equipes(-,nom\_equipe='XV \; de \; France',-,coach:nom) \lor joueurs(-,id\_equipe='FRA',nom,-,-,-,-,-,-) \}\)
Calcul relationnel de n-uplets :
\(R=\{ nom \; | \; (e.coach:nom, e \in equipes) \land e.nom\_equipe='XV \; de \; France' \lor (j.nom:nom, j \in joueurs \land j.id\_equipe='FRA' ) \}\)
SQL :
(SELECT coach AS nom FROM equipes WHERE nom_equipe='XV de France')
UNION
(SELECT nom FROM joueurs WHERE id_equipe='FRA');
Calcul relationnel de domaine :
\(R=\{ id \; | \; joueurs(id\_joueur:id,-,-,-,-,-,-,-,-) \land \neg selections(id\_joueur:id,-,-,-,-,-,-,-,-) \}\)
Calcul relationnel de n-uplets :
\(R=\{ id \; | (j.id\_joueur:id, j \in joueurs) \land \neg (s.id\_joueur:id, s \in selections) \}\)
SQL :
SELECT id_joueur FROM joueurs
EXCEPT
SELECT id_joueur FROM selections;
Calcul relationnel de domaine :
\(R=\{ id \; | \; joueurs(id\_joueur:id,-,-,-,-,-,-,-,-) \land selections(id\_joueur:id,-,-,-,-,-,-,-,-) \}\)
Calcul relationnel de n-uplets :
\(R=\{ id \; | (j.id\_joueur:id, j \in joueurs) \land (s.id\_joueur:id, s \in selections) \}\)
SQL :
SELECT id_joueur
FROM joueurs
INTERSECT
SELECT id_joueur
FROM selections;
Calcul relationnel de domaine :
\(R=\{ (nom,nationalite) \; | \; joueurs(-,id\_equipe:id,nom,-,-,nationalite,-,-,-) \land equipes(id\_equipe:id,-,pays,-) \land pays!=nationalite\}\)
Calcul relationnel de n-uplets :
\(R=\{ (j.nom,j.nationalite) \; | \; j \in joueurs \land e \in equipes \land j.id\_equipe=e.id\_equipe \land e.pays!=j.nationalite\}\)
SQL :
SELECT nom,nationalite FROM joueurs j INNER JOIN equipes e ON (e.id_equipe=j.id_equipe AND e.pays!=j.nationalite);
-- ou
SELECT nom,nationalite FROM joueurs NATURAL JOIN equipes WHERE pays!=nationalite;
Calcul relationnel de domaine :
\(R=\{ nom \; | \; joueurs(id\_joueur,id\_equipe,nom,-,-,-,-,-,-)\)
\(\qquad \qquad \land \; \forall \; match(id\_match,id\_locaux,id\_visiteurs,-,-,-,-,-,-), selections(id\_joueur,id\_match,-,-,-)\)
\(\qquad \qquad \land (id\_equipe=id\_locaux \lor id\_equipe=id\_visiteurs)\}\)
Calcul relationnel de n-uplets :
\(R=\{j.nom \; | \; j \in joueurs \land \; (\forall m \in matchs \; , \; (j.id\_joueur,m.id\_match) \in selections \land\)
\(\qquad \quad (j.id\_equipe=m.id\_locaux \lor j.id\_equipe=m.id\_visiteurs) \}\)
SQL :
L’opérateur n’existe pas en SQL mais peut être exprimé par une double négation (NOT EXISTS)
« Trouver les joueurs tel qu” il n’existe pas de matchs de son equipe pour lesquels il n’ait pas été sélectionné »
SELECT j.nom
FROM joueurs j
WHERE NOT EXISTS ( SELECT id_match
FROM matchs m WHERE j.id_equipe=m.id_locaux OR j.id_equipe=m.id_visiteurs
EXCEPT
SELECT id_match
FROM selections s WHERE j.id_joueur=s.id_joueur);
NB: la notation : attribut:alias
(ex : coach:nom) symbolise un alias
(ex: nom) d”attribut
(ex: coach) .
Table « equipes » | ||||||||||||||||||||||||||||
|
Table « joueurs » | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Table « matchs » | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Table « selections » | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|