Jean-Yves Fvrier
Architecture logicielle
des systmes informatiques
Autocorrection (SQL)
Prsentation
Ce fascicule contient tous les corrigs des exercices du cours, savoir :
la solution des exercices prsents dans les squences de cours ;
le corrig des trois TD.
Que vous dire, si ce nest de jouer le jeu et de ne consulter le corrig quaprs avoir rellement
ralis lexercice, et non aprs avoir vaguement cherch dix secondes ?
Certaines des requtes prsentes ici sont trs longues. Pour vous viter de trop fastidieuses
saisies, elles sont crites dans les bases de donnes Access que je vous ai fournies avec ce
cours. Vous serez averti par la symbolique suivante en fin de requte :
select NomP, PrnomP, count (*) as [Nombre danimaux]
from Animal A, Propritaire P
where P.NumP = A.NumP
group by NomP, PrnomP ;
Requte Vtrinaire/NbrAnimauxParPropritaire
Cela signifie que :
dans les objets Requtes, la requte ci-dessus est enregistre sous le nom NbrAnimauxPar
Propritaire. Vous pouvez alors la visualiser, la modifier
dans le groupe Vtrinaire, vous trouverez un raccourci vers cette requte.
Sommaire
Squence 1 : introduction SQL
17
35
Travaux dirigs 1
49
53
77
Travaux dirigs 2
85
89
93
Travaux dirigs 3
95
3
8 3999 TC PA 00
Squence 1
Introduction SQL
Exercice 1
Il est possible que vos trois livres ne soient pas ceux que je donne ci-dessous. En effet,
loutil de recherche travaillant partir de lendroit o lon est, tout dpend de lenregistrement courant. Ainsi, il faut tre en dbut de table pour avoir rellement les trois
premiers livres. De plus, si la table a t trie, les enregistrements peuvent tre dans un
ordre diffrent.
Ainsi, lobjectif est davoir trouv trois livres de Zola, quels quils soient.
Je vous propose :
le livre 256 : La fortune des Rougon ;
le livre 257 : La cure ;
le livre 258 : Le ventre de Paris.
5
8 3999 TC PA 00
Squence 2
Table Race
NumR
NomR
NomR
Poids
Poids
Teckel sympa
Teckel sympa
Teckel sympa
Yorkshire
2,5
Yorkshire
Yorkshire
2,5
Chat gouttire
Chat gouttire
Chat gouttire
Saluki
20
Saluki
Saluki
20
Caniche royal
25
Caniche royal
Caniche royal
25
Caniche nain
Caniche nain
Caniche nain
Btard
Btard
Btard
14
Chat sphinx
Persan
15
Chat sphinx
Chat sphinx
16
Persan
Persan
La premire requte fournit la rponse la question : Quelles sont les races stockes
dans la base ? .
La seconde fournit la rponse Donnez les races (et leur poids moyen) des animaux
soigns par la clinique .
Vous remarquerez que les deux phrases ont une formulation diffrente (dans lune, je
parle des donnes de la base, dans lautre, des animaux soigns dans la clinique). Cela
na videmment aucune importance. Au travers de lenrobage des questions, il faut bien
comprendre que je veux:
la liste des races (en abrg je veux les races) do select NomR from Race ;
les races avec le poids moyen, do select NomR, Poids from Race.
Dans la suite du cours, je vous demanderai en franais des donnes (liste des races, ge
moyen des animaux soigns en 1999) et vous devrez crire la requte correspondante.
7
8 3999 TC PA 00
Squence 2
Que remarque-t-on ? Les lignes (enregistrements) de la table Race se retrouvent dans les
rsultats des deux requtes. En revanche, les colonnes (champs) ne sont dans la requte
que si elles sont mentionnes dans sa clause select.
Pour une explication dtaille de ce que fait la requte, retournez dans le cours.
Exercice 3
Je ne vous donne pas le tableau des rsultats vous avez d voir que lordre des champs
avait une importance dans la clause select : les champs de la table rsultat sont dans
lordre o ils sont mentionns dans le select.
Pour la suite de la correction voir le cours.
Exercice 4
STOP ! Vous venez dcrire vos premires requtes. Cela mrite des encouragements !
Bravo, continuez !
Voici les requtes dans lordre (je vous rappelle que SQL version Access ne distingue pas
les majuscules des minuscules).
Prnom
Nom et prnom
select Prnom
from Auteur ;
from Auteur ;
Vous remarquerez que jai demand le nom et le prnom dans la deuxime requte. Je
renvois donc les champs dans cet ordre.
Pour la troisime requte, donner toutes les informations revient donner tous les
champs. Et l, quel ordre donner ? Jai mis lordre des champs de la table Auteur. Vous
noterez que cela revient afficher la table dans son intgralit.
Dites-moi, heureusement que je nai pas demand toutes les informations que vous avez
sur les livres, car cela aurait fait beaucoup de champs crire !
Exercice 5
1. Toutes les informations sur les auteurs (prnom avant le nom).
Je veux tous les champs mais dans un ordre diffrent de celui de la base. Je suis donc
oblig de tous les numrer dans lordre o je les veux. Cela donne :
select NumAuteur, Prnom, Nom, DateNaissance, LieuNaissance,
DateDcs, LieuDcs
from Auteur ;
2. Toutes les informations sur les livres.
Comme je ne prcise pas dordre, je vais conserver celui de la base ! Je me contente donc
de demander le champ * :
select *
from Livre ;
8
8 3999 TC PA 00
Requte bizarre.
Ne prenons pas de risque ! Nous allons utiliser notre technique dmulation du fonctionnement de la requte pour tre sr du rsultat.
tapes
1. La table de travail est la table mentionne dans la clause
from.
2. En puisant dans la table de travail, on prend
successivement et dans lordre tous les champs indiqus
dans la clause select. Cela donne la nouvelle table de
travail.
3. La table de travail est le rsultat.
Rsultat
Nous partons de la table Auteur.
On va prendre tous les champs dans lordre
( cause du * ) puis on prend nouveau le
champ Nom.
On a fini.
Nom
Prnom
DateNaissance
LieuNaissance
DateDcs
LieuDcs
Nom
NumAuteur
Prnom
DateNaissance
LieuNaissance
DateDcs
LieuDcs
Exercice 6
Je vous propose :
select NomR as Race, Poids as [Poids moyen (kg)]
from Race ;
Vous noterez que, vu la question (le poids pour chaque race), il est logique de mettre
la race puis le poids. Sinon, on obtiendrait une suite de chiffres sans signification. Cest
une erreur classique.
Exercice 7
Vous devez obtenir un message derreur lexcution vous indiquant que lalias de sortie
Nom est rpliqu. (Alias de sortie est ce que jai appel libell.)
Quen conclure ? Vous vous souvenez que le nom du champ est un identifiant de ce
champ et doit donc tre unique dans une table. Et bien, le libell est identifiant du
champ et doit donc tre unique dans la requte.
9
8 3999 TC PA 00
Squence 2
Exercice 8
Voici le rsultat que lon obtient :
Requte sans as
NomR
Expr1001
Teckel sympa
7000
Yorkshire
2500
Chat gouttire
5000
Saluki
20000
Caniche royal
25000
Caniche nain
5000
Btard
lapin blier nain
6000
Chat sphinx
3000
Persan
3000
Comment expliquer le nom de la seconde colonne ? (Vous devez avoir ExprXXX, XXX tant
un nombre quelconque.) Reprenons le cours : si le nom du champ nest pas prcis par un
libell, SQL reprend celui du champ de la table initiale. Or le second champ nest pas issu
de la table initiale puisque cest un champ calcul. Ainsi, on naffiche pas les donnes du
champ Poids, mais les donnes du champ calcul valant 1000*Poids. Access donne donc
un nom par dfaut : Expr (pour Expression) suivi dun numro.
videmment, ce nom nest pas parlant du tout. Le destinataire du rsultat peut bon
droit sinterroger : que reprsentent les donnes de la seconde colonne ? Le nombre
danimaux soigns ? Le nombre danimaux rpertoris en France ?
Il est donc impratif de toujours nommer un champ calcul.
Exercice 9
1. La requte na aucun sens ! On ne peut pas multiplier un nom de race, donc du texte,
par un nombre. Les calculs numriques sont rservs aux champs numriques. Cest
une rgle de base que vous avez d acqurir dans le cours de programmation.
2. Je vous propose :
select NomProd as [Nom du produit], PrixHT as [Prix HT], PrixHT*1.196 as [Prix TTC]
from Produit ;
3. La notion est celle de donne calcule. Vous vous souvenez sans doute que les donnes calcules, donc retrouvables par calcul, ntaient pas mises dans le MCD. Et bien,
par exemple, on ne met pas la donne PrixTTC dans le MCD vu quavec notre requte,
on sait la recrer.
10
8 3999 TC PA 00
Exercice 10
Je nai rien dire sur la premire requte. Testez-la.
Quant la deuxime, hum, il semblerait que nous violions allgrement la rgle vue dans
lexercice prcdent. Et pourtant, cela fonctionne.
Voyons pourquoi Poids*1000 & " grammes" est malgr tout correct.
Il faut lire cette expression ainsi : (Poids*1000) & " grammes" ; cela signifie que lon
multiplie le poids par mille avant dajouter la chane de caractres. Cela revient donc
concatner une chane un entier. Bon ; cela nest toujours pas correct, sauf que si le
langage y met du sien, on peut sen sortir.
En fait, SQL va convertir lentier en chane de caractres puis lui ajoutera simplement la
chane grammes. Comme toute valeur numrique peut tre convertie en chane, tout se
passe bien. Le rsultat final affich sera videmment une chane de caractres.
Si Poids vaut 2,5, on aura :
Poids*1000 & " grammes"
(2,5*1000) & " grammes"
2500 & " grammes"
[voici ltape cruciale] "2500" & " grammes"
"2500 grammes"
Exercice 11
Il suffit de lire la clause select : Poids > 10 as Gros .
Poids > 10 est une expression boolenne qui est vraie si la variable Poids est suprieure
10. Ainsi, le teckel pesant 7 kg, le test est faux do la valeur 0.
Un gros animal est donc un animal pesant plus de 10 kg.
Exercice 12
Quel est le problme avec cette requte ? Eh bien, le troisime champ Poids (mg) est un
champ calcul bas sur le champ lui-mme calcul Poids (g). Or, jai plus ou moins dit
quun champ calcul devait tre bas sur des champs rels. Cette requte ne devrait donc
pas fonctionner.
Or, elle fonctionne. Comment expliquer cela ? Tout simplement en disant que lorsque
vous utilisez un champ calcul pour en crer un autre, SQL se contente de remplacer le
champ calcul par sa valeur par rapport aux champs rels.
Ainsi, [Poids (g)]*1000 sera traduit par Poids*1000*1000 puisque Poids (g) est dfini par
Poids*1000. SQL considrera donc la requte ainsi :
select NomR, Poids*1000 as [Poids (g)], Poids*1000*1000 as [Poids (mg)]
from Race ;
L, vous serez daccord pour dire quil ny a plus de problme pour excuter la requte
daprs mon mode demploi.
11
8 3999 TC PA 00
Squence 2
Exercice 13
En excutant la requte, on obtient le rsultat suivant :
Expr1000
30
Vous remarquerez que SQL vous renvoie le rsultat sous la forme dune table avec un
seul champ et un seul enregistrement. Est-ce normal ? Oui, car SQL ne sait manipuler que
des tables (donc des champs et des enregistrements). Il est donc naturel quil retourne
tout rsultat sous cette forme.
Si nous navons quun champ, cest que nous navons demand quune valeur dagrgat
(le nombre minimum de pages). Si lon a quun enregistrement, cest tout simplement
parce que le rsultat est unique : il ny a quun minimum pour un ensemble de valeurs
donn.
Notez que le rsultat signifie que le livre qui possde le moins de pages en a trente. Mais
quel est ce livre mystre ! Pour le savoir, je dois parcourir la table (avec loutil Recherche)
pour trouver lenregistrement qui possde la valeur 30 dans la champ Pages.
Seconde partie de la question : pourquoi est-ce que ce nest pas lisible ? Si vous regardez
le rsultat de la requte sans en connatre le texte SQL, vous ne pouvez pas savoir ce que
ce 30 signifie : le nombre dauteurs ? Le nombre de livres lus en 2000 ?
On va profiter du fait que SQL nous donne le rsultat sous forme de table pour nommer
le champ rsultant. Par exemple :
select min(Pages) as [Nbr pages min]
from Livre ;
(testez cette requte.)
Exercice 14
Nombre maximum :
select max(Pages) as [Nbr pages max]
from Livre ;
Rsultat : 1 991 pages
Nombre moyen :
select avg(Pages) as [Nbr pages moy]
from Livre ;
Rsultat : 355,38 pages (jai arrondi)
Aucune difficult
Exercice 15
Je reprends deux phrases de correction de lexercice 13 : Si lon a quun champ, cest
que lon a demand quune valeur dagrgat. Si lon a quun enregistrement, cest tout
simplement parce que le rsultat est unique.
12
8 3999 TC PA 00
Je veux donc obtenir trois valeurs : le nombre minimal, le nombre maximal et le nombre
moyen. Cela me fera trois champs.
Je mattends donc un rsultat sous cette forme :
Select
Min
30
Max
1991
Moy
355,996978851964
Si vous naviez pas russi crire la requte, ressayez en cherchant obtenir le rsultat
ci-dessus.
La solution est simple :
select min(Pages) as Min, max(Pages) as Max, avg(Pages) as Moy
from Livre ;
Dit autrement : je veux un champ appel Min contenant la plus petite valeur affecte
au champ Pages, un champ Max contenant la plus grande et un champ Moy contenant
la valeur moyenne.
Comme chacune de ces trois valeurs est unique, on naura quune seule ligne (enregistrement) rsultat.
Exercice 16
Normalement, vous avez d penser que ma requte donnait le titre du livre ayant le
moins de pages et son nombre de pages. Vous vous attendiez donc connatre enfin le
livre nayant que trente pages !
Or, stupfaction, vous ne pouvez excuter cette requte : vous obtenez un message
derreur : Vous avez essay dexcuter une requte ne comprenant pas lexpression
spcifie titre comme une partie de la fonction dagrgat. Dans la bote de dialogue du
message, il y a un bouton Aide. Si vous ntes pas all voir dans laide, cest une erreur !
Allez-y maintenant.
Je viens de lancer laide sous Access 2003 : on ne comprend pas grand-chose. Mais bon,
ctait quand mme le premier rflexe avoir.
La suite de la correction est suffisamment importante pour tre dans le cours.
Exercice 17
Le nombre de livres dans ma base
select count(NumLivre) as [Nbr livres]
from Livre ;
[rsultat : 2 321]
Attention ! Dans le cours, jai dit que count comptait les valeurs non Null du champ.
Jai donc bien pris soin dutiliser la cl primaire des enregistrements car elle a toujours
une valeur. Testez la requte en remplaant NumLivres par Pages. Vous obtiendrez 2 317
car jai quatre livres non pagins donc pour lesquels je nai pas pu renseigner le champ.
Ne confondez pas Null et nul : une valeur nulle, cest 0. Une valeur Null, cest une absence de valeur.
Par exemple, le nom de jeune fille dun homme est une proprit toujours Null.
13
8 3999 TC PA 00
Squence 2
[rsultat : 721]
Eh eh ! Quitte mettre un champ quelconque, pourquoi ne pas les mettre tous ? Je trouve quainsi cest plus intuitif : on visualise mieux que lon compte les enregistrements.
quelle date ai-je achet mon premier livre ?
select min(DateAchat) as [Date dachat du premier livre]
from Livre ;
[rsultat : 01/03/1987]
Notez bien que les dates sont ordonnes chronologiquement, du pass vers lavenir.
Ainsi, une date du pass sera infrieure une date du futur. La date la plus petite est
donc la plus ancienne. Allez voir la table Livre. Vous remarquerez que beaucoup de livres
nont pas de date dachat. Cest la fameuse valeur pas de valeur Null. Visiblement, ces
absences de valeurs ne sont pas prises en compte pour les calculs de fonctions dagrgat.
Et cest assez raisonnable !
Quel est le prix du livre le plus cher ?
select max(Prix) as [Prix le plus cher]
from Livre ;
[rsultat : 80,26 ]
[rsultat : 09/12/2000]
Lanimal le plus jeune est celui n le plus tard, donc avec la date de naissance la plus
grande. Nous reverrons cela la squence 4.
Combien de races danimaux sont rfrences dans ma base ?
select count(*) as [Nbr de races danimaux]
from Race ;
[rsultat : 10]
[rsultat : 51,37 ]
Exercice 18
Dure en jours entre lachat et la lecture pour chaque livre.
Comment savoir le nombre de jours couls entre deux dates ? Eh bien, comme sous
Excel, il suffit de les soustraire. Bien entendu, il ne faut pas se tromper de sens dans la
14
8 3999 TC PA 00
soustraction : on fait la date la plus grande (date de lecture) moins la plus petite (date
dachat). Il faut galement renvoyer le titre ; sinon, on naura que des chiffres sans signification.
select Titre, Datelecture-DateAchat as
from Livre ;
Temps moyen
Il suffit dappliquer la fonction dagrgat avg au champ calcul Datelecture-DateAchat.
Cette fois, on ne peut plus ajouter de titre car cest interdit avec un agrgat.
select avg(Datelecture-DateAchat) as [Dlai moyen avant lecture (en jours)]
from Livre ;
On obtient 272,78 jours, soit plus de 9 mois. Cette requte est simple. Imaginez que vous
ne disposiez pas de SQL. Comment auriez-vous obtenu ce rsultat la main ? En embauchant un stagiaire qui ferait le calcul ?
Premiers et derniers noms.
select min(NomA) as [Premier nom], max(NomA) as [Dernier nom]
from Animal ;
Nous sommes fonds utiliser min et max puisque lon peut comparer les chanes
de caractres selon lordre alphabtique. En revanche, je vous laisse le soin de tester
select avg(NomA).
Livre lu le jour de son achat.
Comment rpondre cela ? Il nest pas question de rpondre oui ou non. Enfin, ce serait
bien, mais on ne sait pas faire. On va demander le plus petit cart entre la date de lecture
et la date dachat (soit min(DateLecture-DateAchat)). Si cette valeur est nulle (attention,
nulle, pas Null), cest que jai lu au moins un livre le jour de son achat.
select min(DateLecture-DateAchat) as [cart minimum]
from livre ;
On rcupre 0 donc la rponse est oui.
15
8 3999 TC PA 00
Squence 3
Regardez le contenu de la table Race. Vous remarquerez que lon a rcupr uniquement
les noms de race dont le poids moyen des sujets est suprieur dix kilos : a marche !
Pour le fonctionnement, on verra la solution dans lexercice suivant ; je vous lai demand ds maintenant pour vous faire rflchir.
Pour avoir les petits chiens, il faut garder les chiens qui ne sont pas gros, donc qui ne
vrifient pas le critre Poids > 10. Deux solutions : vous prenez la ngation de ce test ou
vous calculez la main cette ngation :
Test
Poids > 10
Ngation la main
Poids <= 10
Dans la suite du cours, je vous indiquerai les oprateurs logiques que vous pourrez
utiliser. En fait, ce sont tous ceux que vous utilisez en algorithmique puisque la notion
dexpression logique est la mme en algorithmique et sous SQL.
Notez le pige classique : la ngation de >, cest <= et non <. En effet, daprs le principe du tiers exclu, si une valeur ne vrifie pas un test, elle vrifie forcment la ngation
de ce test (si x = 6 est faux, alors x 6 est vrai). Dans le doute, il est plus sage dutiliser
loprateur not.
Choisir le bon oprateur de comparaison est crucial en SQL. Chaque anne les tudiants se font avoir ! Et cest dommage car on peut difficilement faire plus bte comme
erreur.
Les deux requtes suivantes rpondent donc la question :
select NomR
from Race
where not (Poids > 10) ;
select NomR
from Race
where Poids <= 10 ;
Squence 3
En excutant lune de ces requtes, vous remarquerez que vous obtenez toutes les races
qui ntaient pas renvoyes quand on demandait les gros animaux. Cest normal puisque
daprs nos critres, un chien qui nest pas gros est petit. Enfin sauf que lon na jamais
la race Btard. Est-ce normal ? Oui, puisque son poids est indfini. Il nest donc pas plus
suprieur quinfrieur ou gal 10.
Exercice 20
Nous allons raisonner sur la requte renvoyant les gros animaux.
Supposons que la clause select soit excute avant le where. On aurait alors quelque
chose du genre :
1. Clause from (la table de travail est celle du from).
2. Clause select : la nouvelle table de travail est constitue en puisant les champs mentionns dans le select (je rsume un peu !).
3. Clause where : les enregistrements de la table de travail ne vrifiant pas la condition sont limins.
Cela est-il correct ? Testons notre requte de lexercice prcdent :
1. [from Race] La table de travail est Race.
2. [select NomR] La nouvelle table de travail est la prcdente dont on ne garde que
le champ NomR.
3. [where Poids > 10] Nous sommes coincs : comment conserver les enregistrements
en fonction de leur valeur pour le champ Poids alors que les enregistrements de la
table de travail ne possdent plus que le champ NomR ? Cela ne fonctionne pas.
Seconde possibilit : la clause where est excute avant le select :
1. Clause from (la table de travail est celle du from).
2. Clause where : les enregistrements de la table de travail ne vrifiant pas la condition sont limins.
3. Clause select : la nouvelle table de travail est constitue en puisant les champs mentionns dans le select (je rsume un peu !).
Cela est-il correct ? Testons notre requte de lexercice prcdent :
1. [from Race] La table de travail est Race.
2. [where Poids > 10] Nous avons encore accs tous les champs de la table initiale.
Nous pouvons donc supprimer ceux ne vrifiant pas la condition.
3. [select NomR] La nouvelle table de travail est la prcdente dont on ne garde que
le champ NomR.
Cest parfait ! Illustration graphique :
1. Clause from : on part de la table Race.
NumR
2
3
4
5
6
8
9
14
15
16
from Race
NomR
Teckel sympa
Yorkshire
Chat gouttire
Saluki
Caniche royal
Caniche nain
Btard
lapin blier nain
Chat sphinx
Persan
Poids
7
2,5
5
20
25
5
6
3
3
18
8 3999 TC PA 00
2. Clause where : on supprime les enregistrements ne vrifiant pas Poids > 10. Il
reste :
from Race where Poids > 10
NumR
NomR
Poids
Saluki
20
Caniche royal
25
3. Clause select : on ne conserve que les champs du select (et on rajoute ventuellement les champs calculs).
select NomR from Race where Poids > 10
NomR
Saluki
Caniche royal
Exercice 21
On obtient les requtes suivantes :
1. Liste des races dont le numro est suprieur 5.
select NomR
from Race
where NumR > 5 ;
Remarquez que quand je demande les races, cest sous-entendu le nom des races et pas autre
chose, notamment pas le poids.
2. Nom du vtrinaire dont le prnom est Paul.
select NomV
from Vtrinaire
where PrnomV = "Paul" ;
Remarquez que SQL ne distingue pas les majuscules des minuscules. Vous pouvez donc crire
Paul, paul, PAUL ou PaUl dans la clause where.
3. Y a-t-il un animal sappelant Vieil Alf ?
select *
from Animal
where NomA = "Vieil Alf" ;
Si on obtient un rsultat, cest que lenregistrement correspondant existe et que la rponse est
oui.
Une autre solution consistait crire select count(*) :
select count(*)
from Animal
where NomA = "Vieil Alf" ;
Cela compte le nombre danimaux sappelant Vieil Alf (donc 0 sil ny en a pas).
19
8 3999 TC PA 00
Squence 3
20
8 3999 TC PA 00
On obtient donc :
select count (*) as [Nombre chiens]
from Animal
where NumR = 3 ;
Notez bien quen crivant la requte dans lordre o les clauses sont excutes (et non dans
lordre o elles sont crites), on ne peut normalement pas se tromper.
Enfin, je vous rappelle que lon peut mettre nimporte quel champ dans le count et donc
galement * , qui est plus court et vous vite davoir vous creuser la tte pour trouver un
champ qui fasse bien !
Exercice 22
Sans passer par les notions SQL, il doit tre vident que lon va obtenir un tableau de la
forme suivante :
Titre
Prnom
Nom
La Piti dangereuse
Stefan
Zweig
Le Docteur Pascal
mile
Zola
Chaque ligne correspond un livre et les diffrentes colonnes donnent les informations
voulues.
Si lon raisonne dun point de vue SQL, on remarque que le rsultat est une table contenant un champ de Livre (Titre) et deux champs dAuteur (Prnom et Nom).
On remarque le ct sympathique de cette reprsentation : intuitivement, on obtient un
tableau classique tout fait simple demploi. Si lon connat SQL, on retrouve la notion
de table comme dans les requtes slection.
Notez bien que lordre des champs na de sens que pour lutilisateur final. Je peux tout
aussi bien crire le tableau prcdent ainsi sil le souhaite :
Prnom
Titre
Nom
Stefan
La Piti dangereuse
Zweig
mile
Le Docteur Pascal
Zola
Je peux donc mlanger les champs des diffrentes tables sans problme : inutile de mettre dabord ceux de Livre, puis ceux dAuteur.
Exercice 23
Jespre que vous navez pas pass une heure sur cette question ! Parce que, ma foi, il
ny a pas de rponse. Cet enregistrement ne correspond rien de rel : jai ajout arbitrairement une race et un vtrinaire. Jaurais pu, de mme, ajouter un mdicament
un livre
Explication (ou excuse ?) rellement donne par un de mes tudiants lorsquil semblait en veille
sur un exercice similaire.
21
8 3999 TC PA 00
Squence 3
La seule chose plausible que vous pourriez me dire est que ce vtrinaire (Michel Rhin)
est spcialis dans cette race (Chat sphinx). Mais, daprs la description du rel, vous
savez pertinemment que nous ne grons aucune spcialit.
La conclusion de lexercice est la suivante :
La chose fondamentale retenir en informatique est que lordinateur ne manipule
que des octets (voire des bits) sans aucune notion de smantique. Il ny a que vous qui
savez ce que reprsentent ces donnes. Plus spcifiquement dans les bases de donnes,
SQL manipule des enregistrements et des champs sans se soucier de la signification des
donnes relles. Comme SQL sait comment ajouter un champ un enregistrement pour
obtenir un enregistrement composite (cest ce que nous venons de faire), il peut ajouter nimporte quel champ de nimporte quelle table un autre enregistrement. Et cela,
mme si lenregistrement rsultant na aucun sens (nous allons le voir dans la suite du
cours).
Ce sera donc vous de prendre en compte la smantique des donnes pour prciser
lesquelles sont pertinentes :
par rapport la ralit : la donne composite forme de la runion arbitraire
dautres donnes na pas forcment de sens : que penser de Jean-Yves CNED Nina ?
Cela ne signifie rien. En revanche, la concatnation dune ville et dun code postal
peut avoir un sens : 54 000 Nancy est correct, 21 000 Nancy est faux ;
par rapport vos besoins : si lon veut le titre dun livre, la donne date dimpression, bien quexistante et valide, est inutile.
Exercice 24
Il suffit de compter pour voir que la table rsultante possde 6 champs et 18 enregistrements. Ces chiffres sont intressants pour nous aider trouver la formule gnrale.
La concatnation de deux enregistrements revient ajouter les champs de lun ceux
de lautre. Ainsi, si les deux tables ont respectivement c1 et c2 champs, la table rsultante
aura c1 + c2 champs.
On prend chaque enregistrement de la 1re table et on le relie successivement avec tous
ceux de la seconde. Cela donne e2 enregistrements. On rpte cela pour les e1 enregistrements de la 1re table. Cela donne donc e1 x e2 enregistrements.
Vrifions :
Dans le produit cartsien tabli prcdemment, on a bien 3+3 = 6 champs et 3x6 = 18
enregistrements. Nos formules sont donc justes.
Exercice 25
Pour avoir le nombre denregistrements dune table, par exemple Auteur, on crira une
requte avec fonction dagrgat :
select count(*) as [Nbr enregistrements]
from Auteur ;
En revanche, il faut compter les champs la main
22
8 3999 TC PA 00
Auteur
livre
champs
12
7+12 = 19
enregistrements
721
2 321
NBR
TABLES
Pratiquer
Consultation
Soin
champs
2+6+5 = 13
enregistrements
26
17
26x17x8 = 3 536
Nous ne ferons pas de nouveau calcul on part de tables toutes petites dont jai pu
numrer compltement le contenu dans le cours et on arrive une table dont le listing
de tous les enregistrements ferait plus de 66 pages (en taille 12).
Exercice 26
Il suffit de taper les requtes et de les excuter.
Exercice 27
Le problme est que le livre Germinal est associ successivement aux 721 auteurs de la
base. Ainsi, on est sr de ne pas se tromper ! Mais, bien videmment, ce nest pas satisfaisant.
Cela vient du fait que chaque livre est successivement associ tous les auteurs (bref,
cela vient du produit cartsien).
Il nous manque donc encore une tape pour obtenir notre rsultat.
Exercice 28
La requte sera :
select NomA, PrnomP, NomP
from Propritaire, Animal ;
On a bien le problme de lanimal associ tous les propritaires.
Je vous rappelle que 1 ko vaut 1024 octets, mais que jarrondis mes calculs.
23
8 3999 TC PA 00
Squence 3
Exercice 29
Cest Josette Mars qui possde Dmon et Frdrique Fvrier qui possde Nina. Comment
ai-je fait pour obtenir ces informations ? Pour chaque animal, je vais dans la table Animal,
je note son numro de propritaire (NumP), puis je vais dans la table Propritaire pour
chercher le nom et le prnom du propritaire correspondant. Voici une illustration :
Table Animal
NumA NomA
lan
02/10/1980
Dmon
05/06/1985
Zo
09/12/2000
Nina
14/01/1996
Niok
01/08/2000
Jeune alf
Pollen
Jafna
23/05/1996
BNJ145
10
Fabel
24/10/1995
11
Tanis
30/06/1994
12
Rio
13
Bipsie
14
Bouboule 01/01/1995
15
Nouki
ERT502
ZEN245
DFG001
Fvrier
Frdrique
OIU115
15
Fvrier
Jean-Yves
14
Mars
Josette
Javelas
Henri
Loriette
Sylvain
BNA485
Fvrier
Jean-Yves
BUI416
30/06/1994
KIU521
06/04/1985
DZE445
MPO444
Table Propritaire
NumP
NomP
PrnomP
Exercice 30
Comme je nai pas prcis de champ particulier, cest que je les veux tous. La requte
excuter est donc :
select *
from Animal, Propritaire ;
Voici le rsultat du produit cartsien (il y a 84 lignes, je nen donne donc quun extrait
car ce qui mintresse, ce sont les champs) :
24
8 3999 TC PA 00
animal.NumP
propritaire.NumP
NomP
PrnomP
AdrP
CodeP
lan
02/10/1980
ERT502
Fvrier
21 000
lan
02/10/1980
ERT502
Fvrier
Jean-Yves
98 765
lan
02/10/1980
ERT502
Mars
Josette
54 000
lan
02/10/1980
ERT502
Javelas
Henri
lan
02/10/1980
ERT502
Loriette Sylvain
4, avenue fleurie
95 000
lan
02/10/1980
ERT502
Fvrier
Jean-Yves
14 000
Dmon 05/06/1985
Fvrier
21 000
Dmon 05/06/1985
Fvrier
Jean-Yves
98 765
Dmon 05/06/1985
Mars
Josette
54 000
Dmon 05/06/1985
Javelas
Henri
Dmon 05/06/1985
Loriette Sylvain
4, avenue fleurie
95 000
Dmon 05/06/1985
Fvrier
Jean-Yves
14 000
Zo
09/12/2000
ZEN245
Fvrier
21 000
Zo
09/12/2000
ZEN245
Fvrier
Jean-Yves
98 765
Zo
09/12/2000
ZEN245
Mars
Josette
54 000
Zo
09/12/2000
ZEN245
Javelas
Henri
Zo
09/12/2000
ZEN245
Loriette Sylvain
4, avenue fleurie
95 000
Zo
09/12/2000
ZEN245
Fvrier
14 000
Jean-Yves
Je vous ai parl de deux champs aux noms tranges. Ce sont animal.NumP et propritaire.NumP. Vous devez comprendre intuitivement ce que sont ces deux champs. En
effet, loprateur . est trs connu en programmation (donnes structures, accs aux
membres des objets). Il a toujours le mme rle, savoir atteindre un objet contenu dans
un autre objet. Ce peut tre :
une variable contenue dans une autre variable (cas des donnes structures) ;
une proprit ou une mthode contenue dans un autre objet (cas de la programmation objet) ;
un champ contenu dans une table.
Ainsi :
animal.NumP doit se lire le champ NumP de la table Animal ;
propritaire.NumP doit se lire le champ NumP de la table Propritaire .
Dune faon gnrale, on crira table.champ et on lira le champ Champ de la table
Table . La question en suspens, cest : pourquoi SQL a-t-il utilis cette notation ? On ne
lavait jamais vue avant, et, dans la table, seuls deux champs ont droit ce traitement.
Pourquoi ne pas avoir crit aussi Animal.NomA par exemple ?
Vous devez tre capable de rpondre cette question. Oui ? Non ? En fait, vous avez d
remarquer que ce sont les champs NumP des tables Animal et Propritaire qui ont t
renomms.
Quelle alternative avions-nous Animal.NumP et Proritaire.NumP ? Eh bien, mettre
NumP tout court. Cela aurait donn :
NumA NomA DateNaissA Tatouage NumR NumP NumP NomP
PrnomP
AdrP
lan
02/10/1980
ERT502
lan
02/10/1980
ERT502
Fvrier Jean-Yves
lan
02/10/1980
ERT502
Mars
Josette
25
8 3999 TC PA 00
Squence 3
7
7
7
7
7
7
NomA
lan
lan
lan
lan
lan
lan
Dmon
Dmon
Dmon
Dmon
Dmon
Dmon
Zo
Zo
Zo
Zo
Zo
Zo
Jeune
Jeune
Jeune
Jeune
Jeune
Jeune
DateNaissA
02/10/1980
02/10/1980
02/10/1980
02/10/1980
02/10/1980
02/10/1980
05/06/1985
05/06/1985
05/06/1985
05/06/1985
05/06/1985
05/06/1985
09/12/2000
09/12/2000
09/12/2000
09/12/2000
09/12/2000
09/12/2000
Tatouage
ERT502
ERT502
ERT502
ERT502
ERT502
ERT502
ZEN245
ZEN245
ZEN245
ZEN245
ZEN245
ZEN245
NumR
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
animal.NumP
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
1
2
3
4
5
6
1
2
3
4
5
6
1
2
3
4
5
6
propritaire.NumP
NomP
Fvrier
Fvrier
Mars
Javelas
Loriette
Fvrier
Fvrier
Fvrier
Mars
Javelas
Loriette
Fvrier
Fvrier
Fvrier
Mars
Javelas
Loriette
Fvrier
PrnomP
Frdrique
Jean-Yves
Josette
Henri
Sylvain
Jean-Yves
Frdrique
Jean-Yves
Josette
Henri
Sylvain
Jean-Yves
Frdrique
Jean-Yves
Josette
Henri
Sylvain
Jean-Yves
AdrP
13, rue de la rpublique
19, rue de la gare
4, rue des Arbres
29, avenue de la libration
4, avenue fleurie
87, square des amis
13, rue de la rpublique
19, rue de la gare
4, rue des Arbres
29, avenue de la libration
4, avenue fleurie
87, square des amis
13, rue de la rpublique
19, rue de la gare
4, rue des Arbres
29, avenue de la libration
4, avenue fleurie
87, square des amis
14
14
14
14
14
14
2
2
2
2
2
2
1
2
3
4
5
6
Fvrier
Fvrier
Mars
Javelas
Loriette
Fvrier
Frdrique
Jean-Yves
Josette
Henri
Sylvain
Jean-Yves
26
8 3999 TC PA 00
Au final, il ne reste que les enregistrements suivants (cette fois, je suis exhaustif) :
Rsultat
NumA
5
6
7
8
2
3
4
9
10
11
12
13
14
15
NomA
Nina
Niok
Jeune alf
Pollen
lan
Dmon
Zo
Jafna
Fabel
Tanis
Rio
Bipsie
Bouboule
Nouki
propritaire.NumP
1
1
2
2
3
3
3
4
4
4
4
5
5
6
NomP
Fvrier
Fvrier
Fvrier
Fvrier
Mars
Mars
Mars
Javelas
Javelas
Javelas
Javelas
Loriette
Loriette
Fvrier
PrnomP
Frdrique
Frdrique
Jean-Yves
Jean-Yves
Josette
Josette
Josette
Henri
Henri
Henri
Henri
Sylvain
Sylvain
Jean-Yves
AdrP
Exercice 31
Normalement, vous navez aucune difficult puisque dans la correction prcdente jai
explicit le critre ncessaire. Pour ne conserver que les enregistrements cohrents, on
va rajouter une clause where :
select *
from Animal, Propritaire
where Animal.NumP = Propritaire.NumP ;
Testez cette requte : on obtient bien le rsultat final de lexercice prcdent.
Pour vrifier mon petit speech prcdent sur lobligation de qualifier un champ ambigu
avec le nom de sa table, testez cette requte :
select *
from Animal, Propritaire
where NumP = NumP ;
Vous aurez un message derreur conforme mes explications.
Pour navoir que les noms, il suffit de les prciser dans la clause select :
select NomA as Animal, NomP as [Nom prop], PrnomP as [Prnom prop]
from Animal, Propritaire
where Animal.NumP = Propritaire.NumP ;
27
8 3999 TC PA 00
Squence 3
Nom prop
Prnom prop
Nina
Fvrier
Frdrique
Niok
Fvrier
Frdrique
Jeune alf
Fvrier
Jean-Yves
Pollen
Fvrier
Jean-Yves
lan
Mars
Josette
Dmon
Mars
Josette
Zo
Mars
Josette
Jafna
Javelas
Henri
Fabel
Javelas
Henri
Tanis
Javelas
Henri
Rio
Javelas
Henri
Bipsie
Loriette
Sylvain
Bouboule
Loriette
Sylvain
Nouki
Fvrier
Jean-Yves
Exercice 32
1. Donnez la liste des chiens (nom) avec leur propritaire associ (nom, prnom et
numro).
Le pige est davoir crit ce qui suit :
select NomA, NomP, PrnomP, NumP
from Animal, Propritaire
where Animal.NumP = Propritaire.NumP ;
Jai enlev les libells des champs dans le select pour ne pas alourdir la lecture. En effet,
le problme nest pas l. Si vous navez pas fait cette requte (ou, et l ce nest pas bien,
si vous avez crit cette requte mais navez pas pris soin de la tester), testez-la sous
Access.
Bien, vous lavez teste et avez obtenu un message derreur dj vu. Que sest-il pass ?
Lorsque SQL excute la requte, il soccupe du from, du where comme vu dans le cours,
puis il soccupe du select. Et, l, SQL est bien ennuy : lorsquil arrive au champ NumP, il
ne sait pas lequel prendre puisque ce champ est prsent dans Animal, mais galement
dans Propritaire.
Vous pourriez me dire que cela na aucune importance puisque lexcution de la clause
where assure que les enregistrements ont la mme valeur pour les champs NumP des
deux tables. Mais, si vous me disiez cela, je vous rpondrais que SQL ne raisonne pas du
tout comme cela : lorsquil soccupe de la clause select, il ne se souvient plus de ce quil
a fait avec le where. Il ne sait donc plus que les deux valeurs sont gales.
Il est impratif de comprendre que les clauses sont excutes de faon tout fait distinctes et tanches.
28
8 3999 TC PA 00
Ainsi, dans toutes les clauses de la requte, il faut qualifier les champs ambigus.
Notez quici, comme les valeurs sont gales, on peut mettre au choix Animal.NumP ou
Propritaire.NumP.
On obtient donc :
select NomA, NomP, PrnomP, Propritaire.NumP
from Animal, Propritaire
where Animal.NumP = Propritaire.NumP ;
2. Donnez les numros des consultations faites par le vtrinaire Violette Carr et
ayant cot plus de 50 .
Faisons toujours nos tapes :
1. On a besoin des tables Vtrinaire (pour avoir le nom) et Consultation (pour avoir
les consultations), donc from Vtrinaire, Consultation (pas dordre particulier).
2. Le produit cartsien impose la jointure dans le where, donc where Vtrinaire.
NumV = Consultation.NumV (cela nous permet davoir le nom du vtrinaire ayant
ralis la consultation).
3. On ne veut pas toutes les consultations mais seulement celles ayant cot plus de
50 . On rajoute donc au where lexpression and PrixC > 50.
4. On ne veut pas toutes les consultations de plus de 50 , mais seulement celles
faites par Violette Carr, donc on rajoute au where lexpression and PrnomV =
"Violette" and NomV = "Carr".
5. On veut uniquement le numro de consultation, donc select NumC.
Au final :
select NumC
from Vtrinaire, Consultation
where Vtrinaire.NumV = Consultation.NumV and PrixC > 50 and
PrnomV = "Violette" and NomV = "Carr" ;
Vrifiez la main puis sur machine que cette requte fonctionne correctement.
3. Nombre danimaux de la race yorkshire.
1. Cest la requte 7 de lexercice 21, sauf que je ne donne plus un numro de race (3)
mais son nom (yorkshire). On a donc besoin de la table Race pour avoir le numro
de race associ au nom yorkshire. Donc from Race, Animal.
2. Un produit cartsien une jointure donc : where Race.NumR = Animal.NumR
3. Comme on veut les yorkshires et pas dautre chien, on aura en plus dans la clause
where : and NomR = "Yorkshire"
4. on veut le nombre denregistrements donc select count(*).
On obtient :
select count(*) as [Nombre Yorkshires]
from Race, Animal
where Race.NumR = Animal.NumR and NomR = "Yorkshire" ;
29
8 3999 TC PA 00
Squence 2
Exercice 33
select NumC
from Vtrinaire V, Consultation
where V.NumV = Consultation.NumV and PrixC > 50 and PrnomV = "Violette"
and NomV = "Carr" ;
Cette requte fonctionne or, je nai dfini un alias que pour une table sur les deux. La leon
est quun alias est propre une table et que lon est libre, pour chaque table, den mettre ou
pas.
Bien entendu, lintrt des alias tant la concision et la lisibilit, il est totalement ridicule de
ne pas sen servir pour chaque table !
select NumC
from Vtrinaire V, Consultation C
where V.NumV = Consultation.NumV and PrixC > 50 and PrnomV = "Violette"
and NomV = "Carr" ;
lexcution, SQL vous demande un paramtre Consultation.NumV. Nous tudierons les
paramtres dans la squence suivante. Sachez juste que cela signifie que SQL ne reconnat pas
Consultation.NumV Cest normal : la table Consultation nexiste plus dans la requte puisquelle a t renomme en C. On constate que la table est vraiment renomme. Lalias est bien
un nouveau nom et non un synonyme.
Exercice 34
Jai presque tout dit dans le cours ! La requte sera :
select DateC
from Consultation C, Pratiquer P, Soin S
where C.NumC = P.NumC and S.NumS = P.NumS and NomS = "Vaccin" ;
Jinsiste sur le fait que lordre des conditions dans le where na aucune importance (pour
la mme raison que 2+3 = 3+2). Je vous conseille nanmoins de mettre dabord toutes les
conditions de jointure puis les autres conditions afin dtre sr de ne pas en oublier.
Une petite remarque en passant : sil y avait eu 50 vaccins le 14/04/2001, jaurais rcupr
50 fois cette date (puisque jaurais 50 enregistrements de Consultation vrifiant le test).
Cest un peu ennuyeux la solution se trouve la squence suivante (ce sera loprateur
distinct).
Exercice 35
Comme vous tes encore jeune dans le monde de SQL, je mastreins dcomposer les
requtes pour bien vous montrer comment procder pour les crire. Noubliez pas que le
jour de lexamen, vous devrez crire les requtes sur papier. Et, hlas, sur papier, les algorithmes et les requtes fonctionnent toujours ! Vous naurez pas lopportunit de tester
sur machine votre production. Vous tes donc susceptible de passer ct derreurs btes
que vous auriez immdiatement identifies sur ordinateur.
30
8 3999 TC PA 00
Il vous faut donc redoubler dattention. Jouez le jeu et travaillez donc comme moi en
dcomposant vos requtes, mme si elles vous semblent simples. En effet, il sagit pour le
moment dacqurir une mthode qui vous sera prcieuse lors de requtes plus ardues.
1. Donnez-moi le nombre de livres crits par M. Zola.
Pour avoir les livres, jai besoin de Livre et pour avoir lauteur (son nom), il faut passer
par Auteur. On aura donc :
1. from Livre L, Auteur A.
Est-il cohrent de faire appel ces deux tables ? Oui, car elles sont lies par un couple
cl primaire/cl trangre rparti dans les deux tables avec le champ NumAuteur.
Nous pourrons donc tablir une condition de jointure.
2. Les deux tables doivent tre accompagnes dune condition de jointure (on vient
de voir ci-dessus que lon avait matire le faire), donc :
where L.NumAuteur = A.NumAuteur.
3. [Un petit rsum : nous en sommes la jointure, cest--dire au produit cartsien
dont on na conserv que les lignes cohrentes. Notre table de travail est pour le
moment constitue de tous les livres associs leur auteur.] Comme on ne veut
que les livres de Zola, on rajoutera la clause where :
and Nom = "Zola".
4. [Nous navons plus que les livres crits par Zola.] Nous ne voulons pas les livres,
mais le nombre de livres, soit select count(*). On rajoutera dailleurs un nom de
champ !
Au final :
select count(*) as [Nbr livres Zola]
from Auteur A, Livre L
where A.NumAuteur = L.NumAuteur and Nom = "Zola" ;
Une remarque importante : si javais deux auteurs diffrents sappelant Zola, par exemple
mile Zola et Honor Zola, la requte me renverrait le nombre de livres total de ces deux
auteurs, soit 91 si lun en avait crit 51 et lautre 40.
Est-ce ennuyeux ? Non : le sujet est explicite. Il suppose clairement que je nai quun Zola
dans ma base. Vous navez donc pas faire le malin et rajouter dans le where Prnom =
"mile" .
2. Quel est le nombre de pages total des livres de la collection 10-18 ?
1. Pour avoir les livres, jai besoin de Livre et cest tout
2. Pas de condition de jointure puisque je nai quune table.
3. Comme on ne veut que les livres de 10-18, on aura where Collection = "10-18".
4. [Nous navons plus que les livres 10-18.] Je veux la somme de toutes les pages, donc
select sum(Pages). Je vous rappelle cette fonction dagrgat sum qui va additionner
toutes les valeurs du champ Pages sur les enregistrements. Et cest bien ce que je
souhaite.
Au final :
select sum(Pages) as [Nbr Pages]
from Livre
where Collection = "10-18" ;
(Le rsultat est 39 026 pages !)
31
8 3999 TC PA 00
Squence 3
3. Je veux la fois le nombre de pages 10-18 mais aussi le nombre de livres 10-18 et le
nombre moyen de pages dun livre 10-18.
Cest le mme principe que lexercice prcdent. Je veux juste plus dinformations, ce qui
me donne :
select sum(pages) as [Nbr pages], count(*) as [Nbr livres],
[Nbr pages]/[Nbr livres] as [Nbr pages moyen]
from Livre
where Collection = "10-18" ;
Au lieu de [Nbr pages]/[Nbr Livres], on pouvait crire Avg(Pages). Rsultat de la requte :
Requte 10/18
Nbr pages
39026
Nbr livres
134
Pour vrifier que cela est correct, je pars de la table de travail aprs from et where et
jarrive au select.
Dj, notre rgle de validation (une requte avec fonction dagrgat ne peut rien contenir dautre) est vrifie : si le troisime champ nest pas proprement parler une fonction dagrgat, cest une opration mathmatique sur des fonctions dagrgat.
On a dj parl du sum(Pages). Le count(*) nous renvoie le nombre denregistrements
de la table de travail, donc le nombre de livres 10-18 puisque la clause where na laiss
que ceux-l. Le dernier champ divise les deux premiers pour obtenir la moyenne. Tout
va bien !
Ces deux dernires requtes ne mettaient pas en uvre de jointure. Et bien oui, il ne
faut pas en mettre partout !
4. Donnez-moi la liste des consultations (date et heure) o Nouki a t soign en donnant, pour chacune delles, les nom et prnom du vtrinaire et le nom des soins
pratiqus.
1. Bon. Pour avoir Nouki, il faut Animal. Pour avoir le vtrinaire, il faut Vtrinaire.
Pour faire le lien entre lanimal et le vtrinaire, il faut Consultation. Pour avoir les
soins pratiqus lors des consultations, il faut Pratiquer et pour avoir le libell des
soins, il faut Soin. Ouf ! Cela nous donne la clause from de la requte ci-dessous.
2. Ces cinq tables donneront quatre conditions de jointure. On ne doit pas les mettre
au pif (il nexiste aucun lien entre Animal et Soin) mais identifier les couples cl
primaire/cl trangre reliant ces tables. Cela nous donne les conditions de jointure
de la requte ci-dessous.
3. On ne veut que les informations lies Nouki, do and NomA = "Nouki" dans le
where.
4. On ne veut que les noms du vtrinaire, le descriptif du soin et les date et heure de
la consultation, do la clause select ; notez bien que lon na pas besoin du nom
de lanimal !
32
8 3999 TC PA 00
On obtient :
select DateC, HeureC, NomV, PrnomV, NomS
from Animal A, Vtrinaire V, Soin S, Pratiquer P, Consultation C
where (A.NumA = C.NumA) and (C.NumV = V.NumV) and (P.NumC = C.NumC)
and (S.NumS = P.NumS) and NomA = "Nouki" ;
Cela donne le rsultat suivant :
Traitements Nouki
DateC
HeureC
NomV
PrnomV
NomS
07/11/2000
13:15
Carr
Paul
Strilisation mle
07/11/2000
13:15
Carr
Paul
Dtartrage
26/08/1996
13:30
Rhin
Michel
Vaccin
26/08/1996
13:30
Rhin
Michel
Radiographie
18/10/2004
11:00
Carr
Violette
Dtartrage
Cest une requte intressante : lorsque Jean-Yves Fvrier emmne Nouki chez lun des
vtrinaires, celui-ci sait immdiatement quels soins ont t donns et par qui. Le problme, cest que les vtrinaires doivent avoir une requte diffrente par animal : si je
veux les traitements qua subi Jeune Alf, il me faut une nouvelle requte avec NomA =
"Jeune Alf". Ce nest pas trs raisonnable. Voyez la squence suivante pour rgler ce
problme.
5. Donnez les noms des lapins bliers nains et des chats sphinx.
Bien entendu, on a besoin de Race et Animal avec une jointure. La seule difficult est de
bien crire la fin de la clause where avec un parenthsage correct : daprs le cours, on
aura where jointure and autres conditions.
Que sera autres conditions ? On veut les races lapin blier nain et galement chat
sphinx. Or, un animal nest que dune race et une seule. Il faut donc utiliser le connecteur
boolen or : on veut les animaux qui sont lapin ou chat .
Au final :
select NomA
from Animal A, Race R
where (A.NumR = R.NumR) and (NomR = "lapin blier nain" or NomR = "chat sphinx") ;
Le rsultat est Jeune Alf et Niok. Notez que lon ne sait pas si ces deux animaux sont des
lapins, des chats ou un de chaque ; cest un peu gnant. Mme si le sujet ne le demande
pas explicitement, il semble plus raisonnable de renvoyer le nom de lanimal et sa race ;
la clause select devient alors :
select NomA, NomR
Mettre un and est une erreur bte mais classique ; mais bte.
33
8 3999 TC PA 00
Squence 4
Exercice 37
Pour la correction, je ne vais pas jouer deviner le fonctionnement des requtes car je
connais le rsultat. tudions donc directement ce dernier :
select NomP, PrnomP
nomP
prnomP
Fvrier
Frdrique
Fvrier
Jean-Yves
Mars
Josette
Javelas
Henri
Loriette
Sylvain
Fvrier
Jean-Yves
Bon, rien dire sur cette requte, elle est tout fait classique. Elle nous servira de rfrence pour celles qui suivent. Vous remarquerez que lon a deux fois Jean-Yves Fvrier.
Un coup dil la table Propritaire nous rassure : il sagit dhomonymes puisque lun
habite Dijon, lautre Caen.
Maintenant, on rajoute le distinct. Cet oprateur ne sapplique quaux enregistrements
entiers. Or, dans la table ci-dessus, on a un doublon (soit un enregistrement prsent deux
fois). Lenregistrement concern et son doublon sont en gras dans la table ci-dessous :
35
8 3999 TC PA 00
Squence 4
prnomP
Fvrier
Frdrique
Fvrier
Jean-Yves
Mars
Josette
Javelas
Henri
Loriette
Sylvain
Fvrier
Jean-Yves
Vous notez que Frdrique Fvrier nest pas concerne puisque, si elle a le mme nom
de famille, elle possde un prnom diffrent.
Comme on enlve les doublons, la requte peut produire lun des rsultats qui suivent :
select distinct (1re solution)
nomP
prnomP
prnomP
Fvrier
Frdrique
Fvrier
Frdrique
Fvrier
Jean-Yves
Mars
Josette
Mars
Josette
Javelas
Henri
Javelas
Henri
Loriette
Sylvain
Loriette
Sylvain
Fvrier
Jean-Yves
Jai laiss lenregistrement conserv en gras : sur les deux, on peut garder le premier ou
le second. Lequel des deux rsultats SQL va-t-il donner ? Cest une question sans objet.
Vous navez qu essayer ! Lordre des enregistrements tant arbitraire dans les tables,
vous ne pouvez ni ne devez tabler sur le fait quun enregistrement sera avant ou aprs
un autre. Si vous voulez imposer un semblant dordre dans les enregistrements, poursuivez le cours !
Exercice 38
Cette requte est absolument identique :
select count (Collection)
from Livre ;
En effet, une requte avec fonction dagrgat ne revoie quun seul enregistrement. Or,
pour avoir un risque denregistrement doublon, il faut en avoir au moins deux ! Ainsi,
mettre distinct ne change absolument rien. Il est donc un peu bte de le mettre. mon
sens, cest une erreur de logique.
Exercice 39
Vous devez avoir crit :
select HeureC
from Consultation
where DateC = 26/08/1996 ;
Je viens de tester cette requte sous Access 2003. Je suis assez tonn car nous nobtenons aucun message derreur. Mais, en tout tat de cause, la requte ne donne aucun
rsultat. Enfin, on obtient un rsultat, qui est : il ny a aucun enregistrement rpondant
36
8 3999 TC PA 00
la requte . Attention, cette phrase est une interprtation du rsultat (un enregistrement vide), elle ne saffiche pas lcran.
Allez voir la suite du cours pour lexplication.
Exercice 40
Vous ne voyez pas ? Si je vous dit 2/5, vous me dites quoi ? 0,4 ? Eh bien, vous avez
raison ! Si je vous dis 2/5/2 ? Eh bien 2/5/2 = (2/5)/2 = 0,4/2 = 0,2.
Bref, 26/08/1996 est une expression mathmatique valant 0,00016283 (26/08/1996 =
26/8/1996 = (26/8)/1996 = 3,25/1996 = 0,00016283).
Exercice 41
Les dates retenues seront postrieures au 31/12/2000 donc au choix :
suprieures strictement au 31/12/2000 ;
suprieures ou gales au 01/01/2001 ;
ce qui donne deux requtes possibles :
select *
select *
from consultation
from consultation
Vous noterez que le sujet ne demandant rien de prcis, je ne me fatigue pas et je renvoie
tous les champs.
Exercice 42
Les consultations de lanne 2000 ont eu lieu du 01/01/2000 au 31/12/2000, ce qui
donne :
select *
from Consultation
where DateC >= #01/01/2000# and DateC <= #31/12/2000# ;
Nous verrons deux autres faons pour faire cela dans la suite du cours.
Exercice 43
Consultations en 2000
Une consultation aura eu lieu en 2000 si son anne est 2000 donc si year (DateC) =
2000. Cela donne :
select *
from Consultation
where year (DateC) = 2000 ;
37
8 3999 TC PA 00
Squence 4
Vous noterez que cette requte est beaucoup plus lisible que celle de lexercice 42. De
plus, elle minimise les risques derreur de rdaction : il ny a plus se creuser la tte pour
choisir les bons oprateurs et connecteurs logiques.
Annes avec au moins une consultation
Pour avoir toutes les annes, noubliez pas le distinct ! En effet, mme si jai 50 consultations en 2000, je ne veux quune seule fois lanne 2000 en rsultat.
select distinct Year (DateC) as [Anne avec consultation(s)]
from Consultation ;
La difficult de cette requte, ctait de penser au distinct.
Exercice 44
Eh bien, pas de difficult particulire :
select count (*)
from Consultation
where DateC= #07/12/2000# and heureC = #12:00# ;
Notez que la requte ne renvoie aucun rsultat sur mon PC. En revanche, si jcris DateC
= #12/07/2000#, cela fonctionne.
En fait, il faut que jcrive la date au format amricain MM/JJ/AAAA. Bien entendu, cela
est en totale contradiction avec le fait quAccess massure quil utilise les rglages dfinis
dans Poste de travail/Panneau de configuration/Options rgionales et linguistiques o
jai naturellement dfini les rglages franais.
Bref, si vous obtenez un rsultat erron, ne vous affolez pas : tentez comme moi de permuter le jour et le mois dans les dates.
Dans un vrai dveloppement dentreprise, il faudrait prendre trs srieusement cela en
compte.
(En fait, ce qui se passe, cest que le moteur Access travaille en interne au format amricain. Et, en tapant une requte ainsi, la conversion nest pas faite.)
Exercice 45
Ma foi, vous devez sans difficult avoir crit :
select NomA
from Animal ;
Exercice 46
Tri mis part, la requte est classique :
select NomA, DateNaissA
from Animal ;
38
8 3999 TC PA 00
Nous voulons la liste trie daprs la date de naissance ; nous aurons donc une clause du
style order by DateNaissA. Seulement, doit-on mettre desc ?
On veut un tri du plus vieux au plus jeune. Or, plus lanimal est vieux, plus il est n il y
a longtemps, donc plus sa date de naissance est petite. Je vous rappelle quune date
antrieure (avant) une autre est dite plus petite.
Si X est n le 07/12/1970 et Y le 15/08/1968, Y est plus vieux et sa date de naissance est
plus petite.
Je veux donc les dates de naissance de la plus petite la plus grande. Cest lordre chronologique standard, il ne faut donc pas mettre desc ! La requte est :
select NomA, DateNaissA
from Animal
order by DateNaissA ;
Testez la requte. Vous remarquerez que les animaux sans date de naissance sont mis en
tte de liste. La valeur Null (signifiant, je vous le rappelle, labsence de valeur) est arbitrairement dfinie comme infrieure toutes les valeurs.
Un bon conseil : lors de requtes o lon vous demande un tri, vrifiez plutt deux fois
quune que votre ordre de tri est correct. Cest dommage dchouer dessus !
Exercice 47
La requte est :
select NomA
from Animal
order by DateNaissA desc ;
Il ny a pas de question se poser pour lordre de tri : comme lordre est le contraire de
celui de lexercice 46, on doit logiquement ajouter desc. La seule autre diffrence avec
la requte prcdente est que je ne renvoie plus DateNaissA dans le select puisque ce
nest plus demand.
Cette requte va-t-elle ou non fonctionner ? Comme je lai dit dans le sujet, tout dpend
du moment de lexcution de la clause order by :
si le tri est effectu alors que lon a tous les champs de la table initiale dans la table
de travail, DateNaissA est encore prsent donc on peut trier les enregistrements en
fonction des valeurs de ce champ ;
en revanche, si lon trie aprs avoir supprim les champs non demands il ne reste
plus que NomA ! Impossible donc de trier selon un autre champ.
Bon. Il est temps de tester ! (Faites-le)
Eh bien, cela fonctionne. Est-ce une surprise ? Ma foi, oui et non : il ny avait aucune
raison de supposer que ce serait lune ou lautre des solutions qui serait retenue : elles
taient toutes les deux plausibles.
Squence 4
Cela dit, il est sympathique que ce soit la premire version qui fonctionne car cest la plus
gnrale (permettant de faire le plus de choses). En effet, cela nous donne lopportunit
de trier les donnes sur des champs absents du rsultat final. Que cela soit une bonne
ide de faire ce genre de chose cest un autre problme !
Cet exercice nous permettra de donner le fonctionnement des requtes avec tri.
Exercice 48
En demandant une liste classe par prix TTC, je sous-entends une liste classe par prix TTC
croissant. Sans prendre en compte le tri, la requte est classique :
select NomM, PrixM*1.196 as [Prix TTC]
from Mdicament ;
Attention bien utiliser le point dcimal (1.196) et non la virgule (1,196). Pourquoi ? Car
avec une virgule, SQL interprterait la clause select comme contenant trois champs puisque
la virgule est le sparateur. Ces champs seraient NomM, PrixM*1 et 196, ce dernier ayant
comme libell Prix TTC.
Vous devez vous douter de lintrt de cet exercice : peut-on trier une requte selon un
champ calcul, et si oui, comment ?
Avant de vous donner la rponse, nous allons voir quil y avait moyen dcrire la requte
sans se poser la moindre question. Il suffisait de faire preuve de bon sens. En effet, si le
prix HT du produit P1 est suprieur celui du produit P2, alors le prix TTC de P1 est galement suprieur celui de P2.
Ce sont des mathmatiques de base :
PrixHTP > PrixHTP PrixHTP *1,196 > PrixHTP *1,196 PrixTTCP > PrixTTCP
1
Ainsi, trier selon le prix TTC ou le prix HT revient absolument au mme ! Et, comme le
prix HT est un champ de la table, nous navons plus de question nous poser. On pouvait
donc crire :
select NomM, PrixM*1.196 as [Prix TTC]
from Mdicament
order by PrixM ;
(Je vous rappelle que le champ sur lequel on trie nest pas ncessairement prsent dans le
select voir lexercice prcdent.)
Bien. Cette astuce tant vue, tchons de rpondre la question : peut-on trier selon un
champ calcul ? Pour le moment, vous devez avoir lesprit deux solutions diffrentes
venant de deux points de vue diffrents.
1. PrixM*1.196 est le champ calcul selon lequel on veut trier ? Et bien, on va ajouter
order by PrixM*1.196 ! Cela donne :
select NomM, PrixM*1.196 as [Prix TTC]
from Mdicament
order by PrixM*1.196 ;
Alors que, en toute rigueur, il faudrait utiliser la virgule puisque cest le sparateur officiel en France.
Mais bon, cette prise en compte des normes franaises nexiste que dans Excel.
40
8 3999 TC PA 00
2. Comme le champ calcul PrixM*1.196 est dot dun libell ainsi que je lai conseill
maintes reprises, je peux tout aussi bien utiliser ce dernier pour ma clause order
by :
select NomM, PrixM*1.196 as [Prix TTC]
from Mdicament
order by [Prix TTC] ;
(Je vous rappelle lobligation de mettre des crochets autour des noms de champs faisant plusieurs mots.)
Que donnent ces deux requtes ? Testez-les ! La premire fonctionne, pas la seconde (
lexcution, vous obtenez un message entrez la valeur du paramtre nous aborderons cela un peu plus loin dans la squence).
Cela va nous permettre de dterminer quand la clause order by est excute. En effet,
nous pouvons trier selon un champ calcul, mais en crivant sa valeur (par exemple
PrixM*1.196). Si lon utilise le libell de ce champ calcul (qui est dfini dans le select),
cela ne fonctionne plus. Cela nous montre que la clause order by est excute avant le
select, ce dont on se doutait puisque lon a encore accs aux champs qui sont supprims
par le select.
Exercice 49
La requte est la suivante :
select NomP, PrnomP
from Proprtaire
order by NomP, PrnomP ;
De faon assez logique, je trie les donnes dans lordre o elles apparaissent dans le
select.
Testez cette requte ; comparez le rsultat avec celui obtenu lorsque lon ne triait que
selon le nom. Vous remarquerez que les trois Fvrier (Frdrique et les deux Jean-Yves)
sont maintenant tris entre eux par ordre alphabtique sur leur prnom.
En effet, daprs mon explication sur le tri multi-champs, ce nest que lorsque les valeurs
sont identiques sur le premier champ (ici, le nom) que lon trie sur le second champ (ici, le
prnom). Jaurais pu rajouter un troisime champ (la ville ou autre) qui aurait permis de
trier les deux homonymes Jean-Yves Fvrier ayant la mme valeur pour les deux champs
de tri.
Exercice 50
Rien de difficile, je voulais juste vous faire trier sur un champ calcul. On obtient :
select NomM, PrixM*1.196 as [Prix TTC]
from Mdicament
order by 2 ;
Cest tout de mme plus lisible que order by PrixM*1.196 !
41
8 3999 TC PA 00
Squence 4
Exercice 51
Cest un exercice pnible car il me faut crire trois requtes presque identiques, une par
tatouage :
select NomA
from Animal
where Tatouage = "ZEN245";
select NomA
from Animal
where Tatouage = "OIU115" ;
select NomA
from Animal
where Tatouage = "TOT020" ;
lexcution de la troisime requte, vous remarquerez que lanimal correspondant
nest pas dans votre base de donnes.
Si je vous avais demand didentifier cinquante tatouages et non trois ? Quel cauchemar !
Nous allons voir dans la suite du cours comment faire cela de faon plus raisonnable.
Exercice 52
Ce nest pas trs dur. Voici un petit rsum du cours indiquant lexcution de la requte :
1. Le from : produit cartsien.
2. le where : pour chaque enregistrement, on teste la condition logique et on ne
garde que les enregistrements qui la vrifient.
Avant toute chose, SQL cherche les paramtres et vous demande leur valeur. Nous avons
le paramtre [Tatouage identifier]. Access va donc ouvrir une bote de dialogue et
vous demander de rentrer une valeur pour ce paramtre. Dans notre cas, vous rentrez
ZEN245.
La requte excute sera donc :
select NomA
from Animal
where tatouage = "ZEN245" ;
Deuxime excution de la requte : vous entrez TOTO020 comme valeur du paramtre.
La requte excute sera donc :
select NomA
from Animal
where tatouage = "TOTO020" ;
Aucun enregistrement nayant cette valeur dans Tatouage, le test nest jamais vrifi. La
requte ne renvoie donc rien.
42
8 3999 TC PA 00
Conclusion de lexercice :
Vous ne saisissez quune fois la valeur du paramtre. Cette valeur sera utilise tout au
long de lexcution de la requte donc pour tous les enregistrements et cest trs bien
ainsi : supposez une table de 50 000 enregistrements o SQL vous demanderait une
valeur du paramtre pour chacun deux !
Corollaire de cela : il est impossible de donner une valeur de paramtre par enregistrement.
Exercice 53
1. Nous allons modifier la 4e requte de lexercice 35 : donnez lhistorique des
traitements subis par un animal donn (donc fourni en paramtre).
Il suffit dadapter un tout petit peu la clause where en changeant la constante Nouki en
paramtre (en gras dans la requte) :
select DateC, HeureC, NomV, PrnomV, NomS
from Animal A, Vtrinaire V, Soin S, Pratiquer P, Consultation C
where (A.NumA = C.NumA) and (C.NumV = V.NumV) and (P.NumC = C.NumC)
and (S.NumS = P.NumS) and NomA = [Nom de lanimal] ;
2. Donnez le prix des consultations ayant eu lieu un jour et une heure donns.
Quand je dis un jour et une heure donns ce sont videmment des paramtres et cest
lutilisateur qui va les fournir. La requte ne doit poser aucun problme :
select PrixC
from Consultation
where DateC = [Date] and HeureC = [Heure] ;
(En testant, mfiez-vous de lventuel problme de la saisie de la date jj/mm/aaaa ou
mm/jj/aaaa.)
Exercice 54
Cet exercice est beaucoup moins vident quil ny parat. Sil vous a paru trs facile,
relisez-vous !
Premire requte
select Coucou
from Livre ;
Recherche des paramtres ventuels. Il y a Coucou ; en effet, ce champ ne fait pas partie
de la table Livre. SQL demande la valeur de ce paramtre ; on rentre Salut !. La requte
excute est alors :
select "Salut !"
from Livre ;
Une seule table dans le from, pas de clause where je vous gte. Tous les enregistrements de Livre sont conservs ; et les champs ? lesquels on garde ? Uniquement un
champ calcul, la constante Salut ! Comme cest un champ calcul sans libell, son nom
est Exprxxx.
43
8 3999 TC PA 00
Squence 4
Le rsultat est donc un seul champ et 2 321 enregistrements (le nombre de livres) avec la
valeur Salut ! pour chaque enregistrement.
Seconde requte
select *
from Auteur
where NomAuteur = "Stendhal" ;
On effectue la recherche des paramtres ventuels. Il y en a un ! En effet, le champ contenant le nom de lauteur dans Auteur est Nom. NomAuteur tant inconnu, cest donc
un paramtre. SQL vous demandera sa valeur, et l, deux cas possibles :
1. Vous entrez la valeur Stendhal.
La clause where est alors where "Stendhal" = "Stendhal". En dautres termes, la condition est quivalente 2 = 2, soit la constante vrai. Chaque enregistrement vrifie
donc trivialement le test. La requte revient :
select *
from Auteur ;
Le rsultat est donc la table Auteur.
2. Vous entrez autre chose que Stendhal, par exemple Nina.
La clause where est alors where "Nina" = "Stendhal". En dautres termes, la condition
est quivalente 3 = 2, soit la constante faux. Aucun enregistrement ne vrifie donc
le test. Le rsultat de la requte est alors rien (aucun enregistrement).
Si vous avez trouv cela, bravo !
Exercice 55
Les deux premires requtes sont simples :
select count (*) as [Nbr livres]
from Livre ;
from Auteur ;
Exercice 56
Supposons que vous ayez sauvegard les deux premires requtes sous les noms NbrLivres
et NbrAuteurs. Comme ces requtes possdent des fonctions dagrgat, elles nont quun
enregistrement. Effectuer leur produit cartsien revient par consquent les concatner.
Il ny a rien dautre faire !
La requte est :
select *
from NbrLivres, NbrAuteurs ;
Avouez que cest fort simple !
44
8 3999 TC PA 00
Dans lexercice 36, nous navions pas pu rcuprer le nombre de collections car
count (distinct Collection) ne fonctionne pas sous Access. Nous allons donc passer par
deux requtes. La premire renverra les collections (avec un distinct) et la seconde comptera leur nombre.
Appelons ListeCollections la requte suivante :
select distinct Collection
from livre ;
Le nombre de collections sera alors le rsultat de :
select count(*) as [Nombre de collections]
from ListeCollections ;
Exercice 57
Pas de difficult particulire. On obtient :
select NomA
from Animal A, Consultation C
where (A.NumA = C.NumA) and (DateC >= #01/03/1998#) and (DateC <= #01/07/1998#) ;
et :
select NomM, PrixM
from Mdicament
where (PrixM >= 6) and (PrixM <= 15)
order by 2 ;
Vous noterez cependant :
1. Il faut utiliser des comparateurs larges (<= et >=) et non stricts (< ou >) dans les
deux requtes vu la formulation du sujet : sans prcision contraire, les comparateurs doivent toujours tre larges.
2. Il ne faut pas se tromper dans le sens des comparateurs avec les dates (erreur bte
mais classique mais bte).
3. Comme je trie par prix (seconde requte), je renvoie galement le prix des mdicaments pour que lutilisateur comprenne mon tri.
Exercice 58
Ce nest pas difficile si vous tes rigoureux.
Premire requte :
select NomA
from Animal A, Consultation C
where (A.NumA = C.NumA) and (DateC between #01/03/1998# and #01/07/1998#) ;
45
8 3999 TC PA 00
Squence 4
Deuxime requte :
select NomM, PrixM
from Mdicament
where PrixM between 6 and 15
order by 2 ;
Troisime requte :
select NomP
from Propritaire
where NomP between "F" and "L" ;
Nous sommes daccord que cela fonctionne car, daprs lordre alphabtique :
F < Fvrier < G < H < I < J < Javelas < K < L < Loriette
On rcupre donc Fvrier et Javelas. Comme on na pas prcis distinct, on rcupre les
trois Fvrier.
Exercice 59
Impossible dutiliser between car les valeurs ne sont pas contigus. Il faut donc crire une
tripote de conditions relies par un or :
select NomR
from Race
where (Poids = 7) or (Poids = 2.5) or (Poids = 20) ;
(Attention : en SQL, le nombre 2,5 scrit 2.5)
Exercice 60
Pffft ! Sans problme :
select NomR
from Race
where Poids in (7, 2.5, 20) ;
Exercice 61
Bien. Comme il ny a pas de type de mdicaments, on ne peut pas faire quelque chose du
style where NumType = 5 (5 tant alors le numro du type vermifuge). Il faut connatre
le nom des diffrents vermifuges et les tester.
select NomM, PrixM
from Mdicament
where (NomM = "Vermifuge pte") or (NomM = "Vermifuge cachet") ;
(notez bien le or).
46
8 3999 TC PA 00
Exercice 62
Nous voulons tous les mdicaments dont le nom commence par Vermifuge, soit :
select NomM, PrixM
from Mdicament
where NomM like "Vermifuge*" ;
Exercice 63
En dautres termes, je veux les animaux qui nont aucune valeur pour tatouage :
select NomA
from Animal
where Tatouage is null ;
47
8 3999 TC PA 00
Travaux dirigs 1
49
8 3999 TC PA 00
Travaux dirigs
7. Donnez le total des jours dabsence pris par un salari donn (tous contrats confondus).
select sum(DureA) / 2 as [Jours dabsence]
from absence A, contrat C, salari S
where (A.NumC = C.NumC) and (C.NumS = S.NumS) and (NomS = [Nom du salari]) ;
Attention au pige : je demande un nombre de jours et les dures dabsence sont dcomptes en
demi-journes. Il faut donc diviser par deux.
8. Quels salaris ont eu des absences non autorises au cours du mois courant ?
select NomS
from salari S, contrat C, typeAbsence T, absence A
where (S.NumS = C.NumS) and (C.NumC = A.NumC) and
(A.NumTA = TA.NumTA) and (AutorisTA = false) and
(Month(DateDbut) = Month(Date())) and
(Year(DateDbut) = Year(Date())) ;
Au lieu de AutorisTA = false, on pouvait crire not(AutorisTA). Cest plus lgant. Attention
lexpression le mois courant . Si nous sommes le 08/11/2007, le mois courant nest pas
novembre, mais novembre 2007. Si lon ne prend pas en compte lanne, on aura le cumul des
absences pour tous les mois de novembre (2007, 2006, 2005).
9. Salaire mensuel brut moyen des salaris.
select avg(SalaireBrutMens) as [Salaire moyen]
from contrat ;
10. Salaires mensuels bruts maximum et minimum des CDI signs cette anne.
select min(SalaireBrutMens) as [Salaire min],
max(SalaireBrutMens) as [Salaire max]
from contrat C, typeContrat T
where (C.NumTC = T.NumTC) and (LibellTC = "CDI") and (Year(DateSig)=Year(Date())) ;
11. Salaire annuel net du contrat numro 144. On supposera que le salaire net reprsente 80 % du brut et que le salari touche une participation annuelle gale 95 %
de son salaire brut mensuel.
select SalaireBrutMens*0.8*12 + SalaireBrutMens*0.95 as [Salaire net annuel]
from contrat
where NumC = 144 ;
50
8 3999 TC PA 00
Travaux dirigs
Le salaire net annuel, cest le salaire net mensuel (SalaireBrut*0.8) multipli par 12 (les 12 mois
de lanne) plus lintressement (SalaireBrut*0.95).
Si vous avez ralis ces requtes sans trop de problmes, vous avez parfaitement assimil
le cours. Bravo ! Il ne vous reste plus qu attaquer la suite.
Je prcise que le rel modlis ntant pas simple, les questions poses pouvaient parfois
tre un peu ambiges. Ne vous traumatisez donc pas si vous avez eu une lecture diffrente
du sujet. Les divergences dinterprtations taient possibles dans ce TD.
51
8 3999 TC PA 00