Vous êtes sur la page 1sur 7

IN306 : Alg`

ebre relationnelle et SQL - corrig


e

SID

http://www.tofgarion.net/lectures/IN306

Ce document est un ensemble dexercices permettant de vous exercer `a la manipulation de lalg`ebre relationnelle
et de SQL.

Une base de donn


ees de ventes
Soit la base de donnees relationnelle de ventes de schema suivant :
Client(noClient, nom, noTel, adresse)
Article (noArticle, description, prixUnitaire, qteEnStock)
Commande (noCommande, dateCommande, noClient)
LigneCommande (noCommande, noArticle, quantit)
noCommande r
eference Commande.noCommande
noArticle r
eference Article.noArticle
Livraison (noLivraison, dateLiv)
DetailLivraison (noLivraison, noCommande, noArticle, qteLivree)
noLivraison r
eference Livraison.noLivraison
noCommande r
eference Commande.noCommande
noArticle r
eference Article.noArticle

1. formuler en alg`ebre relationnelle les requetes suivantes.


(a) le numero de commande et la date de commande des commandes du client 10 dont le numero
de commande est superieur `
a 5.
noCommande,dateCommande (noClient=10 AND noCommande5 Commande)
(b) les numeros des articles commandes au moins une fois par le client 10 apr`es le 01/06/2000.
noArticle (dateCommande01 /06 /2000 AND noClient=10 Commande 1 LigneCommande)
(c) les numeros de commande des commandes qui ont ete passees `a la meme date que la commande
2.
noCommande (Commande 1dateCommande dateCommande ((noCommande=2 Commande)))
(d) Les numeros et noms des clients qui nont pas passe de commande au mois de mars de lannee
2000.
noClient,nom Client noClient,nom (dateCommande0 2000 03 01 0 AND dateCommande0 2000 03 31 0 (Client 1
Commande))
(e) Les numeros des articles qui apparaissent dans toutes les commandes du client 10.
noArticle (N oCA) noArticle (((noArticle (N oCA)) N oC) N oCA)
avec
N oC
=
noCommande (noClient=10 (Commande))
et
noCommande,noArticle (LigneCommande 1 NoC ).
On pourra se referer `
a la section 3 pour plus dexplications.
2. formuler les requetes precedentes en SQL.
Voici les differentes requetes :
1

N oCA

SELECT noCommande, dateCommande


FROM Commande
WHERE ((noClient = 10) AND (noCommande >= 5));

SELECT noArticle
FROM Commande NATURAL JOIN LigneCommande
WHERE ((dateCommande >= 2000-06-01) AND (noClient = 10));

SELECT noCommande
FROM Commande JOIN (SELECT * FROM Commande WHERE (noCommande = 2)) ON dateCommande;

On pouvait egalement utiliser une sous-requete :


SELECT noCommande
FROM Commande WHERE dateCommande =

(SELECT * FROM Commande WHERE (noCommande = 2));

SELECT noClient, nom


FROM Client
EXCEPT
SELECT noClient, nom
FROM Client NATURAL JOIN Commande
WHERE (dateCommande LIKE 2006-3-%);

la derni`ere requete est la plus compliquee. . . On peut la reformuler de la facon suivante : on cherche
les numeros darticles n tels quil nexiste pas de commande c telle que :
c est une commande du client 10 ;
il nexiste pas de ligne de commande correspondant `
a c telle que n apparaisse dans la ligne de
commande (ouf !)
Ce qui sexprime par :
SELECT noArticle
FROM Article
WHERE NOT EXISTS
(SELECT noCommande
FROM Commande
WHERE ((noClient = 10) AND NOT EXISTS
(SELECT *
FROM LigneCommande
WHERE (LigneCommande.noArticle = Article.noArticle) AND
(LigneCommande.noCommande = Commande.noCommande)
))
);

Une base de donn


ees dentreprise

Considerons une base de donnees relationnelle contenant des informations sur des employes. Elle
poss`ede plusieurs tables :
2

Employe(NSS, Nom, Prenom, DateNaissance, Adresse, Salaire, NDep, Superieur)


Superieur r
eference Employe.NSS
NDep r
eference Departement.NDep
Departement(NDep, NomD, Directeur)
Directeur r
eference Employe.NSS
Projet(NPro, NomP, Lieu, NDep)
NDep r
eference Departement.NDep
Travaille(NSS, NPro, Heures)
NPro r
eference Projet.NPro
NSS r
eference Employe.NSS

Lattribut Superieur dans la relation Employe contient le numero de securite sociale du superieur
direct de lemploye. Chaque employe appartient `a un departement et travaille sur un ou plusieurs projets.
Chaque projet est rattache `a un departement qui peut etre different de celui des employes travaillant sur
ce projet.
Considerons les requetes suivantes :
1. date de naissance et adresse de Juliette Rochat ;
2. nom et adresse des employes qui travaillent au departement de recherche ;
3. nom des employes qui travaillent plus de 10 heures sur un projet `a Gen`eve ;
4. nom des projets sur lesquels travaillent Jean Muller et Annie Grandjean ;
5. nom et prenom des employes qui ne travaillent sur aucun projet ;
6. numero des projets qui ont au moins un participant de chaque departement ;
7. nom des employes qui ne travaillent pas sur un projet `a Gen`eve ;
8. pour chaque projet, lister le nombre demployes de sexe feminin ;
9. nom des employes qui ne travaillent que sur des projets `a Gen`eve.
Questions :
1. ecrire en alg`ebre relationnelle les requetes 1, 2, 3 et 5 ;
Voici les requetes demandees :
DateNaissance, Adresse (Prenom=Juliette AND Nom=Rochat (Employe))
Nom, Adresse (NomD=Recherche (Employe 1 Departement))
Nom (Heures>10 AND Lieu=Gen`eve ((Projet 1 Travaille) 1NSS = Employe.NSS Employe))
Nom, Prenom (Nom, Prenom, NSS (Employe) Nom, Prenom, NSS (Travaille 1 Employe))
2. ecrire en SQL toutes les requetes precedentes.
Voici les requetes demandees :
SELECT DateNaissance, Adresse FROM Employe
WHERE ((Nom = Rochat) AND (Prenom = Juliette));

SELECT Nom, Adresse


FROM Employe NATURAL JOIN Departement
WHERE (NDep = Recherche);

SELECT DateNaissance, Adresse FROM Employe


WHERE ((Nom = Rochat) AND (Prenom = Juliette));

la question pouvait presenter des ambiguites. On pouvait considerer que la requete portaient sur
les projets impliquant Jean Muller ou Annie Grandjean (le et portant alors sur les projets).
Dans ce cas :
SELECT NomP
FROM Employe JOIN (Projet NATURAL JOIN Travaille) USING NSS
WHERE (((Nom = Muller) AND (Prenom = Jean)) OR
((Nom = Grandjean) AND (Prenom = Annie)));

On pouvait egalement considerer que lon cherchait les projets impliquant `a la fois Annie Grandjean
et Jean Muller. Dans ce cas :
SELECT NPro, NomP
FROM Employe JOIN (Projet NATURAL JOIN Travaille) USING NSS
WHERE ((Nom = Grandjean) AND (Prenom = Annie))
INTERSECT (
SELECT NPro, NomP
FROM Employe JOIN (Projet NATURAL JOIN Travaille) USING NSS
WHERE ((Nom = Muller) AND (Prenom = Jean))
);

Dans ce cas, on utilise NPro pour pouvoir verifier que les projets sont bien identiques. On peut
ensuite refaire une projection pour nobtenir que les noms.
SELECT Nom
FROM (
SELECT NSS, Nom FROM Employe
EXCEPT (
SELECT NSS, Nom
FROM Employe JOIN (Projet NATURAL JOIN Travaille) USING NSS
)
);

Une autre requete equivalente :


SELECT Nom
FROM (
SELECT NSS, Nom FROM Employe
WHERE NSS NOT IN SELECT NSS FROM Travaille
);

On utilise NSS car des personnes peuvent avoir le meme nom.


on cherche `
a compter en fait le nombre de departements par projets :
SELECT NPro, COUNT(NDep)
FROM Employe JOIN (Projet NATURAL JOIN Travaille) USING NSS
GROUP BY NPro
HAVING COUNT(NDep) = (SELECT COUNT (*) FROM Departement);

SELECT Nom
FROM (
SELECT NSS, Nom FROM Employe
EXCEPT (
SELECT NSS
FROM Employe JOIN (Projet NATURAL JOIN Travaille) USING NSS

WHERE (Lieu = Geneve)


)
);

SELECT NPro, NomP, COUNT(NSS)


FROM Employe JOIN (Projet NATURAL JOIN Travaille) USING NSS
WHERE (NSS = 2%)
-- syntaxe a definir proprement
GROUP BY NPro

SELECT NSS, Nom


FROM Employe JOIN (Projet NATURAL JOIN Travaille) USING NSS
WHERE (Lieu = Geneve)
EXCEPT (
SELECT NSS, Nom
FROM Employe JOIN (Projet NATURAL JOIN Travaille) USING NSS
WHERE (Lieu <> Geneve)
);

Il faut egalement enlever les employes qui ne travaillent sur aucun projet.

Corrig
e question e de lexercice 1

Je vous propose de regarder plus en detail le corrige de la question e de lexercice 1. La question est :
quels sont les numeros des articles qui apparaissent dans toutes les commandes du client 10 ? . Jai
tourne un peu en rond avant de trouver une solution propre.
La question nest pas evidente `a formuler en alg`ebre relationnelle. . . On va donc dans un premier temps
proposer une solution en SQL, car laspect declaratif du langage permet de lexprimer plus facilement.
Pour cela, je vais reformuler la question. On cherche les numeros darticles na tels que ces numeros
apparaissent dans toutes les commandes du client 10. On cherche donc les numeros darticles na tels quil
nexiste pas de commande du client 10 dans laquelle na napparat pas. Et hop, on a la solution :)
Je vais construire la solution pas `
a pas, en me permettant dutiliser la variable na dans les etapes
intermediaires. Tout dabord, on va travailler sur les numeros de commandes du client 10. Voici la requete
permettant davoir les numeros de commande du client 10 (facile) :
SELECT noCommande
FROM Commande
WHERE (noClient = 10);

On peut remarquer ensuite que si lon connat un numero de commande nc du client 10, on peut trouver
les tuples de LigneCommande correspondant `a cette commande et tels que le numero de larticle soit na :
SELECT *
FROM LigneCommande
WHERE (LigneCommande.noArticle = na) AND
(LigneCommande.noCommande = nc);

Ensuite, on utilise cette requete pour obtenir les numeros de commande du client 10 tels que larticle
na napparaisse pas dans la commande :
SELECT noCommande
FROM Commande
WHERE ((noClient = 10) AND NOT EXISTS

(SELECT *
FROM LigneCommande
WHERE (LigneCommande.noArticle = na) AND
(LigneCommande.noCommande = Commande.noCommande)
));

On remarquera que la variable nc utilisee precedemment disparat, puisque Commande.noCommande va


maintenant faire reference au numero de commande du tuple que lon est en train de manipuler (puisque
que lon est dans une clause WHERE).
Reste `a se debarrasser de na et construire la requete compl`ete. On va pouvoir le faire en utilisant
la requete solution suivante :
SELECT noArticle
FROM Article
WHERE NOT EXISTS
(SELECT noCommande
FROM Commande
WHERE ((noClient = 10) AND NOT EXISTS
(SELECT *
FROM LigneCommande
WHERE (LigneCommande.noArticle = Article.noArticle) AND
(LigneCommande.noCommande = Commande.noCommande)
))
);

Important : Il ne faut pas oublier que la clause WHERE est evaluee pour chaque
tuple des relations considerees, ce qui permet dutiliser Article.noArticle par
exemple.
Reste `a exprimer cette requete en alg`ebre relationnelle. . . Le plus gros probl`eme qui se pose est le fait
que nous navons pas le droit dutiliser des variables intermediaires (on est en math, donc pas deffet de
bord).
Dans un premier temps, on peut trouver les numeros de commande du client 10 :
noCommande (noClient=10 (Commande)). Appelons la relation obtenue N oC. On peut ensuite trouver pour
chaque commande du client 10 les articles correspondants : noCommande,noArticle (LigneCommande 1
NoC ). Appelons la relation obtenue NoCA.
Prenons un exemple. Voici une instance de NoC :
noCommande
1
2
3
Voici une instance de NoCA :
6

noCommande
1
1
2
2
2
3
3
3

noArticle
100
101
100
101
105
100
101
106

Dans ce cas, on voit que les articles 100 et 101 apparaissent dans toutes les commandes du client 10.
On devrait donc obtenir pour solution une table Sol de la forme suivante :
noArticle
100
101
Cest l`a o`
u ca devient difficile. Quelle est la propriete verifiee par Sol ? En fait, Sol est la table maximale
(au sens du nombre de tuples contenus) telle que :
N oC Sol N oCA
Linclusion est ici `
a prendre au sens de linclusion des ensembles de tuples des relations. Sil ny a
pas darticles apparaissant dans toutes les commandes, Sol ne poss`ede pas de tuples. La condition de
maximalite est necessaire, car sinon Sol pourrait ne contenir que le premier tuple et ca marcherait.
Il nous reste donc `
a definir une operation permettant d inverser 1 loperation pour trouver Sol.
On va y aller doucement, en detaillant les etapes. . .
Tout dabord, on remarque que (noArticle (N oCA)) N oC nous donne une table reliant les numeros
de commande `
a tous les articles commandes par le client 10 (dans notre exemple, on aurait ainsi un
tuple (1, 106) dans cette table). Donc ((noArticle (N oCA)) N oC) N oCA nous donne une table dont les
tuples (noCommande, noArticle) qui representent le fait quun article napparat pas dans une commande
particuli`ere. Donc noArticle (((noArticle (N oCA)) N oC) N oCA) nous donne les numeros darticles qui
napparaissent pas dans au moins une commande. La solution est donc donnee (ouf !) par :
noArticle (N oCA) noArticle (((noArticle (N oCA)) N oC) N oCA)
Remarque importante : Promis, il ny aura plus de questions comme ca `
a
lexamen :)

1. Cest bien s
ur une fausse inversion car on a une inclusion et non pas une
egalit
e.