Requêtes SQL
Judicaël Courant
Informatique Commune, MP/MP*
2018-W03-4
Lignes directrices
1 Exemple étudié
2 La requête SELECT élémentaire
3 Sous-requêtes
4 RequêtesSELECTcomplexes
Exemple étudié La requête SELECT élémentaire Sous-requêtes RequêtesSELECTcomplexes
On va travailler sur un exemple de base de données cinématographique (simpliste) qui comprendra les tables suivantes :
Personnedécrivant les personnes (acteurs et réalisateurs) qui nous intéresseront.
Filmqui nous donnera les titres des films et leurs dates de réalisation.
Acteurqui nous dira qui a joué quel personnage dans quel film.
Exemple étudié La requête SELECT élémentaire Sous-requêtes RequêtesSELECTcomplexes
Table des personnes ( Personne )
nom prénom date_naissance
Kubrick Stanley 1928
Spielberg Steven 1946
Eastwood Clint 1930
Cumberbatch Benedict 1976
Freeman Martin 1971
Leone Sergio 1929
McGuigan Paul 1963
Sellers Peter 1925
Coppola Francis Ford 1939
Coppola Sofia 1971
Table des films ( Film )
titre date_film
Gran Torino 2008
The good, the Bad and the Ugly 1966
Study in Pink 2010
Schindler’s List 1993
Dr Strangelove 1964
Invictus 2009
Table des acteurs ( Acteur )
nom prenom titre personnage
Eastwood Clint The good, the Bad and the Ugly Blondie Eastwood Clint Gran Torino Walt Kowalski Cumberbatch Benedict Study in Pink Sherlock Holmes Freeman Martin Study in Pink Dr John Watson Selers Peters Dr Strangelove Dr Strangelove Selers Peters Dr Strangelove Group Capt. Lionel Mandrake
Selers Peters Dr Strangelove President Merkin Muffley
Exemple étudié La requête SELECT élémentaire Sous-requêtes RequêtesSELECTcomplexes
Table des réalisateurs ( Realisateur )
titre nom prenom
Gran Torino Eastwood Clint
The good, the Bad and the Ugly Leone Sergio
Study in Pink McGuigan Paul Schindler’s List Spielberg Steven Dr Strangelove Kubrick Stanley Invictus Eastwood Clint
Exemple étudié La requête SELECT élémentaire Sous-requêtes RequêtesSELECTcomplexes
Syntaxe
La requête a la forme suivante : 4 SELECT [DISTINCT]champs 1 FROMtables
2 WHEREexpression-filtrage
3 GROUP BYexpression-regroupement 5 HAVINGexpression-filtrage
6 ORDER BYexpression-ordre
Lire la requête dans l’ordre des numéros pour comprendre ce qu’elle fait !
Exemple 1
Dresser une table des triplets(n,p,a)des acteurs nommésd et prénommésp ayant joué dans un film l’annéea.
SELECT DISTINCT nom, prenom, date_film FROM Film JOIN Acteur
ON Film.titre = Acteur.titre;
Alternativement :
SELECT DISTINCT nom, prenom, date_film FROM Film, Acteur
WHERE Film.titre = Acteur.titre;
Exemple 2
Dresser une table des triplets(n,p,n0,p0)des réalisateurs prénommésp et nommésnayant dirigé l’acteur nommén0et prénommép0strictement avant l’année 2010.
SELECT DISTINCT R.nom, R.prenom, A.nom, A.prenom FROM Film AS F
JOIN Acteur AS A ON A.titre = F.titre
JOIN Realisateur AS R ON R.titre = F.titre WHERE date_film < 2010;
Exemple étudié La requête SELECT élémentaire Sous-requêtes RequêtesSELECTcomplexes
Exemple 3
Et si on veut le nombre d’acteurs dirigés par un réalisateur : SELECT R.nom, R.prenom, COUNT(*)
FROM Film AS F
JOIN Acteur AS A ON A.titre = F.titre
JOIN Realisateur AS R ON R.titre = F.titre WHERE date_film < 2010
GROUP BY R.nom, R.prenom;
Il y a un petit problème, le voyez-vous ? (Combien Kubrick a t-il dirigé d’acteurs ?)
Exemple étudié La requête SELECT élémentaire Sous-requêtes RequêtesSELECTcomplexes
Exemple 3 (bis)
Pour le corriger, on peut tenter :
SELECT R.nom, R.prenom, COUNT(DISTINCT A.nom) FROM Film AS F
JOIN Acteur AS A ON A.titre = F.titre
JOIN Realisateur AS R ON R.titre = F.titre WHERE date_film < 2010
GROUP BY R.nom, R.prenom;
Maison peut a priori avoir deux acteurs différents avec le même nom.
MalheureusementCOUNT(DISTINCT R.nom, R.prenom) n’est pas grammatical en SQL. . .
Interlude : une requête bizarre
La requête suivante est invalide :
SELECT R.nom, R.prenom, date_film, COUNT(*) FROM Film AS F
JOIN Acteur AS A ON A.titre = F.titre
JOIN Realisateur AS R ON R.titre = F.titre WHERE date_film < 2010
GROUP BY R.nom, R.prenom;
Règle : lorsqu’on utiliseGROUP BY, dans leSELECT, seuls peuvent apparaître les colonnes sélectionnées pour faire le regroupement ou des valeurs agrégées.
Exemple 4
Comme précédemment, on veut les réalisateurs et le nombre d’acteurs qu’ils ont dirigé mais uniquement pour ceux qui ont au moins dirigé deux acteurs.
SELECT R.nom, R.prenom,
COUNT(DISTINCT R.nom) AS total FROM Film AS F
JOIN Acteur AS A ON A.titre = F.titre
JOIN Realisateur AS R ON R.titre = F.titre WHERE date_film < 2010
GROUP BY R.nom, R.prenom HAVING total >= 2;
Exemple étudié La requête SELECT élémentaire Sous-requêtes RequêtesSELECTcomplexes
Exemple 5
On veut enfin trier le résultat par ordre décroissant de nombre d’acteurs dirigés puis de nom puis de prénom :
SELECT R.nom, R.prenom,
COUNT(DISTINCT R.nom) AS total FROM Film AS F
JOIN Acteur AS A ON A.titre = F.titre
JOIN Realisateur AS R ON R.titre = F.titre WHERE date_film < 2010
GROUP BY R.nom, R.prenom HAVING total >= 2
ORDER BY total DESC, R.nom ASC, R.prenom ASC;
Exemple étudié La requête SELECT élémentaire Sous-requêtes RequêtesSELECTcomplexes
Principe
Pour réussir à résoudre le problème des doublons dans la table précédente, il suffirait de savoir remplacer la jointure de la requête précédente par une expression qui donnerait la table des quadruplets(n,p,n0,p0)disant qui a dirigé qui, sans doublon.
Ça tombe bien : en SQL, partout où on peut mettre un nom de table, on peut remplacer ce nom par une sous-requête SELECT.
Mise en œuvre
Cela permet d’écrire
SELECT n, p, COUNT(*) AS total FROM
(SELECT DISTINCT R.nom AS n, R.prenom, R.nom, R.prenom
FROM Film AS F
JOIN Acteur AS A ON A.titre = F.titre
JOIN Realisateur AS R ON R.titre = F.titre WHERE date_film < 2010)
GROUP BY n, p HAVING total >= 2;
Principe
On peut obtenir la réunion de tables produites par plusieurs requêtes élémentaires avec le mot cléUNIONde la façon suivante :
SELECT... FROM... WHERE... GROUP BY... HAVING...
UNION
SELECT... FROM... WHERE... GROUP BY... HAVING...
...
SELECT... FROM... WHERE... GROUP BY... HAVING...
ORDER BY...
Notez qu’il n’y a qu’une seule clauseORDER BYpour l’ensemble des clauses.
Exemple étudié La requête SELECT élémentaire Sous-requêtes RequêtesSELECTcomplexes
Opérateurs disponibles
En plus de l’opérateurUNION, on peut utiliser INTERSECTpour calculer l’intersection.
EXCEPTpour calculer la différence.