© Your Copyright
L’algèbre relationnelle propose un ensemble d’opérations élémentaires formelles sur les relations dans le but de créer de nouvelles relations.
Ces nouvelles relations constitueront le résultat d’une requête formulée sur le système d’Information à l’aide du langage SQL.
On distingue trois familles d’opérateurs relationnels :
- les opérateurs unaires qui sont les plus simples (projection,restriction) et qui portent sur une seule table
- les opérateurs binaires ensemblistes (union,intersection,différence) entre deux ensembles (relations)
- les opérateurs binaires ou n-aires (produit cartésien,jointure,division) entre deux ou plusieurs ensembles (tables).
les opérateurs dérivés se déduisent des opérateurs de base.
Les équivalences algébriques sont à la base des optimisations de requêtes sur une base de données.
Soit les tables :
table \(S\)
X | Y | Z |
---|---|---|
1 | 1 | 1 |
2 | 2 | 2 |
3 | 3 | 3 |
table \(T\)
X | Y |
---|---|
1 | 1 |
2 | 3 |
3 | 3 |
Quel sera le résultat de la requête : \(R=\cap(\Pi_{(X,Y)}( \sigma_{[Z!=1]}(S)),T)\)
L’ensemble contient un seul élément : \(\{(3,3)\}\)
Vérification en décomposant la requête :
Soit les tables :
table \(S\)
X | Y | Z |
---|---|---|
1 | 1 | 1 |
2 | 2 | 2 |
3 | 3 | 3 |
table \(T\)
X | Y |
---|---|
1 | 1 |
2 | 3 |
3 | 3 |
en considérant les instances de tables suivantes contenant un seul enregistrement :
table S
:
X | Y |
---|---|
1 | 2 |
table T
:
X | Y |
---|---|
1 | 3 |
appliquez les expressions algébriques sur les instances de tables ci-dessus pour justifier vos réponses,
Clavier | Action |
---|---|
F1 | Afficher une aide technique |
F2 | Afficher une aide pédagogique |
Ctrl-A | Tout sélectionner |
Ctrl-C | Copier la sélection dans le presse-papier |
Ctrl-V | Copier le presse-papier dans la sélection |
Ctrl-X | Couper la sélection et la copier dans le presse-papier |
Ctrl-Z | Annuler la modification |
Maj-Ctrl-Z | Rétablir la modification |
Menu | Action |
---|---|
Ré-initialiser les sorties | |
Faire apparaître le menu d'aide | |
Valider la zone de saisie | |
Initialiser la zone de saisie | |
Charger le contenu d'un fichier dans la zone de saisie | |
Sauvegarder le contenu de la zone de saisie dans un fichier | |
Imprimer le contenu de la zone de saisie |
en considérant les tables suivantes :
table S
:
X | Y |
---|---|
1 | 2 |
table T
:
X | Y |
---|---|
1 | 3 |
On peut vérifier que l’équivalence :
- \(\Pi_{X}(\cap(S,T))=\cap(\Pi_{X}(S),\Pi_{X}(T))\)
est fausse.
En effet :
- \(\cap(S,T)=\{\}\)
donc : \(\Pi_{X}(\cap(S,T))=\{\}\)
- \(\Pi_{X}(S)=\{ 1 \}\) et \(\Pi_{X}(T) =\{ 1 \}\)
donc : \(\cap(\Pi_{X}(S),\Pi_{X}(T))=\{ 1 \}\)
par conséquent :
- \(\Pi_{X}(\cap(S,T)) \neq \cap(\Pi_{X}(S),\Pi_{X}(T))\)
On peut également vérifier que l’équivalence :
- \(\Pi_{X}(\setminus(S,T))=\setminus(\Pi_{X}(S),\Pi_{X}(T))\)
est fausse.
En effet :
- \(\setminus(S,T)=\{(1,2) \}\)
donc : \(\Pi_{X}(\setminus(S,T))=\{ 1 \}\)
- \(\Pi_{X}(S) = \{ 1 \}\) et \(\Pi_{X}(T) = \{ 1 \}\)
donc : \(\setminus(\Pi_{X}(S),\Pi_{X}(T)) = \{\}\)
par conséquent :
- \(\Pi_{X}(\setminus(S,T)) \neq \setminus(\Pi_{X}(S),\Pi_{X}(T))\)
La seule équivalence vraie est celle de la distributivité de la projection sur l’union (\(\cup(S,T)\)) :
- \(\Pi_{X}(\cup(S,T))=\cup(\Pi_{X}(S),\Pi_{X}(T))\)
On peut vérifier sur l’exemple précédent :
- \(\cup(S,T)=\{(1,2),(1,3) \}\)
donc : \(\Pi_{X}(\cup(S,T))=\{ 1 \}\)
- \(\Pi_{X}(S) = \{ 1 \}\) et \(\Pi_{X}(T) = \{ 1 \}\)
donc : \(\cup(\Pi_{X}(S),\Pi_{X}(T)) = \{ 1 \}\)
par conséquent :
- \(\Pi_{X}(\cup(S,T))=\cup(\Pi_{X}(S),\Pi_{X}(T))\)
On formulera ici les recherches d’information en algèbre relationnelle 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
);
Algèbre relationnelle :
\(R=\Pi_{(biere,couleur)}(bieres)\)
SQL :
SELECT couleur,biere FROM bieres;
Algèbre relationnelle :
\(R=\sigma_{[origine="France"]}(bieres)\)
SQL :
SELECT * FROM bieres WHERE origine='France';
Algèbre relationnelle :
\(R=\times(bars,bieres)\)
SQL :
SELECT * FROM bars, bieres;
-- ou
SELECT * FROM bars CROSS JOIN bieres;
Algèbre relationnelle :
\(R=\cup(\Pi_{(pays)}(bars),\Pi_{(origine)}(bieres))\)
SQL :
(SELECT pays AS nom FROM bars)
UNION
(SELECT origine AS nom FROM bieres);
Algèbre relationnelle :
\(R=\setminus(\Pi_{(pays)}(bars),\Pi_{(origine)}(bieres))\)
SQL :
(SELECT pays AS nom FROM bars)
EXCEPT
(SELECT origine AS nom FROM bieres);
Algèbre relationnelle :
\(R=\cap(\Pi_{(pays)}(bars),\Pi_{(origine)}(bieres))\)
SQL :
(SELECT pays AS nom FROM bars)
INTERSECT
(SELECT origine AS nom FROM bieres);
Algèbre relationnelle :
\(R=\Pi_{pays}(\Join_{[pays=origine]}(bars,bieres))\)
SQL :
SELECT pays FROM bars INNER JOIN bieres ON(pays=origine);
-- ou
SELECT pays FROM bars,bieres WHERE pays=origine;
Algèbre relationnelle : \(R=\div(S(X,Y),T(Y))\)
Dans le cas des bars qui servent des bières :
- \(R=\div(services(id\_bar,id\_biere),bieres(id\_biere))\)
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 DISTINCT id_bar
FROM services s1
WHERE NOT EXISTS (
SELECT *
FROM bieres b
WHERE NOT EXISTS ( SELECT *
FROM services s2
WHERE s1.id_bar=s2.id_bar AND s2.id_biere=b.id_biere )
);
-- si on souhaite plus d'informations sur les bars
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)
);
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)
);
Algèbre relationnelle :
\(\displaystyle R=\Pi_{(nom,prenom)}(joueurs)\)
SQL :
SELECT nom,prenom FROM joueurs;
Algèbre relationnelle :
\(\displaystyle R=\sigma_{[id\_equipe="FRA"]}(joueurs)\)
SQL :
SELECT * FROM joueurs WHERE id_equipe='FRA';
Algèbre relationnelle :
\(R=\times(equipes,joueurs)\)
SQL :
SELECT * FROM equipes, joueurs;
-- ou
SELECT * FROM equipes CROSS JOIN joueurs;
Algèbre relationnelle :
\(R=\cup(\Pi_{(coach)}(\sigma_{[id\_equipe='FRA']}(equipes),\Pi_{(nom)}(\sigma_{[id\_equipe='FRA']}(joueurs)))\)
SQL :
(SELECT coach AS nom FROM Equipes WHERE id_equipe='FRA')
UNION
(SELECT nom FROM Joueurs WHERE id_equipe='FRA');
Algèbre relationnelle :
\(R=\setminus(\Pi_{(id\_joueur)}(joueurs),\Pi_{(id\_joueur)}(selections))\)
SQL :
SELECT id_joueur FROM joueurs
EXCEPT
SELECT id_joueur FROM selections;
Algèbre relationnelle :
\(R=\cap(\Pi_{(id\_joueur)}(joueurs),\Pi_{(id\_joueur)}(selections))\)
SQL :
SELECT id_joueur
FROM joueurs
INTERSECT
SELECT id_joueur
FROM selections;
Algèbre relationnelle :
\(R=\Pi_{(nom,nationalite)}\Join_{[joueurs.id\_equipe=equipes.id\_equipe \land nationalite!=pays]}(joueurs,equipes)\)
SQL :
SELECT (nom,nationalite) FROM equipes e INNER JOIN joueurs j ON (e.id_equipe=j.id_equipe AND e.pays!=j.nationalite);
-- ou
SELECT (nom,nationalite) FROM joueurs NATURAL JOIN equipes WHERE pays!=nationalite;
Algèbre relationnelle : \(R=\div(S(X,Y),T(Y))\)
Dans le cas du toutnoi des six nations :
- \(R=\div(selections(id\_joueur,id\_match),matchs(id\_match))\)
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);
Formulation SQL :
- On pourra vérifier les requêtes SQL correspondantes aux questions précédentes avec les instances de tables suivantes :
Table « equipes »
id_equipe nom_equipe pays coach FRA XV de France France Novès ANG XV de la Rose Angleterre Jones GAL XV du Poireau Pays de Galles Gatland IRL XV du Trèfle Irlande Schmidt ECO XV du Chardon Ecosse Cotter ITA Azzuri Italie Brunel
Table « joueurs »
id_joueur id_equipe nom prenom position nationalite naissance taille poids 1 ECO Laidlaw Greg 1/2 melee Ecosse 1985-10-12 1.75 80 2 ECO Hogg Stuart Arriere Ecosse 1992-06-24 1.8 80 3 ECO Dunbar Alex 3/4 centre Ecosse 1990-04-23 1.91 80 4 ECO Russell Finn 1/2 ouverture Ecosse 1992-09-23 1.83 80 5 ECO Swinson Tim 2eme ligne Angleterre 1987-02-17 1.95 80 6 ECO Gray Richie 2eme ligne Ecosse 1989-08-24 2.06 80 7 IRL Earls Keith 3/4 centre Irlande 1987-10-02 1.8 80 8 IRL Henderson Iain 2eme ligne Irlande du Nord 1992-02-21 1.98 80 9 IRL Jackson Paddy 1/2 ouverture Irlande du Nord 1990-04-05 1.78 80 10 IRL Stander Christiaan Johan 3eme ligne centre Afrique du Sud 1992-01-05 1.89 80 11 IRL Gilroy Craig 3/4 aile Irlande du Nord 1991-03-11 1.83 80 12 IRL Ringrose Garry 3/4 centre Irlande 1995-01-26 1.87 80 13 IRL Best Rory Talonneur Irlande du Nord 1982-08-15 1.8 80 14 ANG Te'o Ben centre Nouvelle-Zélande 1987-01-27 1.89 80 15 ANG Farrell Owen 3/4 centre Angleterre 1991-09-24 1.88 80 16 ANG Daly Elliot 3/4 centre Angleterre 1992-10-08 1.84 80 17 ANG Youngs Tom Talonneur Angleterre 1987-01-28 1.75 80 18 ANG Cole Dan Pilier Angleterre 1987-05-09 1.91 80 19 FRA Slimani Rabah Pilier France 1989-10-18 1.78 80 20 FRA Lopez Camille 1/2 ouverture France 1989-04-03 1.75 80 21 FRA Fickou Gael 3/4 centre France 1994-03-29 1.9 80 22 FRA Spedding Scott Arriere Afrique du Sud 1986-05-04 1.88 80 23 ITA Gori Edoardo 1/2 melee Italie 1990-03-05 1.78 80 24 ITA Canna Carlo 1/2 ouverture Italie 1992-08-25 1.91 80 25 ITA Parisse Sergio 3eme ligne Argentine 1983-09-12 1.96 80 26 GAL Davies Jonathan 3/4 centre Angleterre 1988-04-05 1.86 80 27 GAL Williams Liam 3/4 aile Pays de Galles 1991-04-09 1.88 80 28 GAL North George 3/4 aile Angleterre 1992-04-13 1.92 80 29 GAL Halfpenny Leigh Arriere Pays de Galles 1988-12-22 1.78 80 30 GAL Biggar Dan 1/2 ouverture Pays de Galles 1989-10-16 1.88 80
Table « matchs »
id_match id_locaux id_visiteurs jour horaire locaux_score visiteurs_score stade spectateurs 1 ECO IRL 2017-02-04 15:25:00 27 22 Murrayfield 67144 2 ANG FRA 2017-02-04 17:50:00 19 16 Twickenham 81902 3 ITA GAL 2017-02-05 15:00:00 7 33 Stadio olympico 40986 4 ITA IRL 2017-02-11 15:25:00 10 63 Stadio olympico 50197 5 GAL ANG 2017-02-11 17:50:00 16 21 Millennium Stadium 74500 6 FRA ECO 2017-02-12 16:00:00 22 16 Stade de France 75283 7 ECO GAL 2017-02-25 15:25:00 Murrayfield 8 IRL FRA 2017-02-25 17:50:00 Aviva Stadium 9 ANG ITA 2017-02-26 16:00:00 Twickenham 10 GAL IRL 2017-03-10 21:05:00 Millennium Stadium 11 ITA FRA 2017-03-11 14:30:00 Stadio olympico 12 ANG ECO 2017-03-11 17:00:00 Twickenham 13 ECO ITA 2017-03-18 13:30:00 Murrayfield 14 FRA GAL 2017-03-18 15:45:00 Stade de France 15 IRL ANG 2017-03-18 18:00:00 Aviva Stadium
Table « selections »
id_joueur id_match essais transformations penalites 2 1 2 0 0 3 1 1 0 0 1 1 0 3 2 7 1 1 0 0 8 1 1 0 0 9 1 1 2 1 14 2 1 0 0 15 2 0 1 3 16 2 0 0 1 19 2 1 0 0 20 2 0 1 3 23 3 1 0 0 24 3 0 1 0 26 3 1 0 0 27 3 1 0 0 28 3 1 0 0 29 3 0 3 4 27 5 1 0 0 29 5 0 1 3 16 5 1 0 0 17 5 1 0 0 15 5 0 1 3 24 4 0 1 1 7 4 2 0 0 10 4 3 0 0 11 4 3 0 0 12 4 1 0 0 9 4 0 9 0 21 6 1 0 0 20 6 0 1 5 2 6 1 0 0 5 6 1 0 0 4 6 0 0 2 20 8 0 0 0 20 11 0 0 0 20 14 0 0 0