Vous êtes sur la page 1sur 15

Requête!3!: Donner la liste de tous les genres de film.

Bases de Données
SELECT DISTINCT GENRE
FROM FILM
TD : langage assertionnel – SQL
Trouver le titre et l’année des films de science fiction dont le budget
Requête!4!:
dépasse 5.000.000 $.
Corrigé SELECT TITRE, ANNÉE
FROM FILM
WHERE GENRE = ‘SciFi’
Liste des requêtes à exprimer en SQL. AND BUDGET > 5000000
Tracer le graphe des clés étrangères avant de commencer à répondre aux requêtes.
Graphe de la requête :
PERSONNE

GENRE = ‘SciFi’
BUDGET > 5000000
ACTEUR
CINÉMA
F

DISTRIBUTION
TITRE, ANNÉE

FILM PASSE SALLE


Res
Requêtes élémentaires

Requête!5!: Donner le nombre de films par genre.


Requête!1!: Retrouver la liste de tous les films.
SELECT GENRE, COUNT (*)
SELECT *
FROM FILM
FROM FILM
GROUP BY GENRE

Requête!2!: Retrouver la liste des films dont la longueur dépasse 180 min.
Requête!6!: Donner le nombre de films de 1960 par genre.
SELECT *
SELECT GENRE, COUNT (*)
FROM FILM
FROM FILM
WHERE LONGUEUR > 180
WHERE ANNÉE = 1960
GROUP BY GENRE
Requêtes faciles Graphe de la requête : la requête imbriquée ne contribue pas au résultat

Requête!7!: Trouver le titre des films réalisés par Roman Polanski.


PRÉNOM = ‘Roman’
NOM = ‘Polanski’
Forme plate!:
RÉALISATEUR = NUMP
SELECT F.TITRE
FROM FILM F, PERSONNE P
F P
WHERE F.RÉALISATEUR = P.NUMP
AND P.PRÉNOM = ‘Roman’

TI
TR
AND P.NOM = ‘Polanski’

E
Graphe de la requête :
Res
PRÉNOM = ‘Roman’
NOM = ‘Polanski’
RÉALISATEUR = NUMP
Requête!8!: Quels sont les acteurs comiques (nom, prénom) qui ont joué dans un
film de Spielberg.
F P Graphe de la requête :
TI
TR
E

SPÉCIALITÉ =
‘Comique’

Res A NUMF = NUMF


N UM RÉALISA
T EU R = N
P= UMA
UM
Forme imbriquée!:
N D F NOM =
‘Spielberg’
SELECT TITRE
FROM FILM PR
PA
WHERE RÉALISATEUR IN ( PR
ÉN
OM
SELECT NUMP ,N
OM
FROM PERSONNE
WHERE PRÉNOM = ‘Roman’
AND NOM = ‘Polanski’ ) Res

Forme plate :
SELECT PA.PRÉNOM, PA.NOM
FROM PERSONNE PA, DISTRIBUTION D, FILM F, PERSONNE PR
WHERE PA.NUMP = D.NUMA

Corrigé du TD SQL (BD-Filmographie) 2


AND D.SPÉCIALITÉ = ‘Comique’ Requête!9!: Trouver le titre et l’année du film le plus long.
AND D.NUMF = F.NUMF
AND F.RÉALISATEUR = PR.NUMP Forme imbriquée!:
AND PR.NOM = ‘Spielberg’ SELECT TITRE, ANNÉE
FROM FILM
Forme imbriquée!: WHERE LONGUEUR = (
SELECT PRÉNOM, NOM SELECT MAX (LONGUEUR)
FROM PERSONNE FROM FILM )
WHERE NUMP IN (
SELECT NUMA Requêtes de difficulté moyenne
FROM DISTRIBUTION
WHERE SPÉCIALITÉ = ‘Comique’ Requête!10!: Nom et prénom des acteurs qui ont joué Gavroche dans les
AND NUMF IN ( différentes versions des!«!Misérables!» avec les dates
correspondantes.
SELECT NUMF
FROM FILM
Forme plate :
WHERE RÉALISATEUR IN (
SELECT P.PRÉNOM, P.NOM, F.DATE
SELECT NUMP
FROM PERSONNE P, DISTRIBUTION D, FILM F
FROMPERSONNE WHERE P.NUMP = D.NUMA
WHERE NOM = ‘Spielberg’ ) ) )
AND D.RÔLE = ‘Gavroche’
AND G.NUMF = F.NUMF
Graphe de la requête : seule la variable PA contribue au résultat, on obtient trois
niveaux d‘imbrication AND F.TITRE = ‘Les misérables’

Graphe de la requête :

SPÉCIALITÉ =
‘Comique’ RÔLE =
‘Gavroche’
NUMF = NUMF NUMP = NUMA
MA RÉALISA
= NU TEUR = NU NUMF = NUMF
MA
MP
NU D F NOM =
D
TITRE =
‘Spielberg’
‘Les misérables’
PR
PA P F
PR
ÉN PR
O ÉN TE
M, OM DA
NO ,N
M OM

Res Res

Corrigé du TD SQL (BD-Filmographie) 3


Forme imbriquée SQL-92!: Forme imbriquée SQL-92!:
SELECT P.PRÉNOM, P.NOM, F.DATE SELECT DISTINCT PRÉNOM, NOM
FROM PERSONNE P, FILM F FROM PERSONNE
WHERE F.TITRE = ‘Les misérables’ WHERE NUMP IN (
AND (P.NUMP, F.NUMF) IN ( SELECT RÉALISATEUR
SELECT NUMA, NUMF FROM FILM
FROM DISTRIBUTION WHERE (RÉALISATEUR, NUMF) IN (
WHERE RÔLE = ‘Gavroche’ ) SELECT NUMA, NUMF
FROM DISTRIBUTION ) )
Graphe de la requête : la requête imbriquée ne contribue pas au résultat et est
liée deux fois à la requête englobante Graphe de la requête :
RÉALISATEUR = NUMA

RÔLE = F D
‘Gavroche’


A NUMF = NUMF
NUM NUM

A
P= F=N
NUM

LIS
UM F
D

MA
AT
TITRE =

NU
EU
‘Les misérables’

=
MP
=N
F

NU
UM
P P

P
PR
ÉN E
OM D AT
,N
OM PRÉNOM, NOM

Res Res

Requête!11!: Donner le nom et le prénom des réalisateurs qui ont joué dans au
Requête!12!: Quel est le total des salaires des acteurs du film «!Nuits blanches à
moins un de leurs propres films.
Seattle!».
Forme plate :
Forme plate :
SELECT DISTINCT P.PRÉNOM, P.NOM
SELECT SUM (D.SALAIRE)
FROM PERSONNE P, FILM F, DISTRIBUTION D
FROM DISTRIBUTION D, FILM F
WHERE P.NUMP = F.RÉALISATEUR
WHERE DISTRIBUTION.NUMF = F.NUMF
AND F.NUMF = D.NUMF
AND F.TITRE = ‘Nuits blanches à Seattle’
AND D.NUMA = F.RÉALISATEUR
Forme imbriquée :
SELECT SUM (SALAIRE)

Corrigé du TD SQL (BD-Filmographie) 4


FROM DISTRIBUTION Requête!14!: Trouver le genre des films des années 80 dont le budget moyen
WHERE NUMF IN ( dépasse 200.000 $.
SELECT NUMF SELECT GENRE
FROM FILM FROM FILM
WHERE TITRE = ‘Nuits blanches à Seattle’ ) WHERE ANNÉE BETWEEN 1980 AND 1989
GROUP BY GENRE
Graphe de la requête : HAVING AVG (BUDGET) > 200000

Requêtes plus complexes


TITRE =
NUMF = NUMF
‘Nuits blanches à Seattle’

Requête!15!: Pour chaque film de Spielberg (titre, année), donner le total des
D F
salaires des acteurs.
SA
LA

Forme plate :
IR
E

SELECT F.TITRE, F.ANNÉE, SUM (D.SALAIRE)


M
SU FROM FILM F, DISTRIBUTION D, PERSONNE P
WHERE F.NUMF = D.NUMF
Res AND F.RÉALISATEUR = P.NUMP
AND P.NOM = ‘Spielberg’
GROUP BY F.TITRE, F.ANNÉE
Requête!13!: Donner la moyenne des salaires des acteurs par film, avec le titre et
l’année correspondants.
Forme imbriquée SQL-89 :
Forme SQL-89 : SELECT F.TITRE, F.ANNÉE, SUM (D.SALAIRE)
SELECT F.TITRE, F.ANNÉE, AVG (D.SALAIRE) FROM FILM F, DISTRIBUTION D
FROM FILM F, DISTRIBUTION D WHERE F.NUMF = D.NUMF
WHERE F.NUMF = D.NUMF AND F.RÉALISATEUR IN (
GROUP BY F.TITRE, F.ANNÉE SELECT NUMP
FROM PERSONNE
Forme SQL-92 : WHERE NOM = ‘Spielberg’ )
SELECT F.TITRE, F.ANNÉE, AVG (D.SALAIRE) GROUP BY F.TITRE, F.ANNÉE
FROM FILM F, DISTRIBUTION D
WHERE F.NUMF = D.NUMF Forme imbriquée SQL-92!
:
GROUP BY F.NUMF SELECT F.TITRE, F.ANNÉE, X.SUMSAL
-- Si NUMF a bien été déclaré clé primaire de la relation FILM FROM FILM F, (
SELECT NUMF, SUM (SALAIRE) AS SUMSAL
FROM DISTRIBUTION

Corrigé du TD SQL (BD-Filmographie) 5


GROUP BY NUMF ) AS X AND C.NUMC = S.NUMC
WHERE F.NUMF = X.NUMF AND S.NBPLACES >= 200
AND F.RÉALISATEUR IN ( AND S.TAILLE_ÉCRAN > 30
SELECT NUMP AND S.NUMC = P.NUMC
FROM PERSONNE AND S.NUMS = P.NUMS
WHERE NOM = ‘Spielberg’ ) AND P.HORAIRE < ’22!:00’
AND P.NUMF = F.NUMF
Requête!16!: Lister les cinémas dont la taille moyenne d'écran est supérieure à 40 AND F.RÉALISATEUR = P.NUMP
mètres carrés. AND P.PRÉNOM = ‘Elia’
AND P.NOM = ‘Kazan’
Forme plate :
SELECT C.NOM, C.VILLE Graphe de la requête :
FROM CINÉMA C, SALLE S
WHERE C.NUMC = S.NUMC TAILLE_ÉCRAN > 30 HORAIRE <
NBPLACES >= 200 ‘22:00’
GROUP BY C.NUMC, C.NOM, C.VILLE
HAVING AVG (S.TAILLE_ÉCRAN) > 40 ) MC
NUMC = NUMC
NUMF = NUMF RÉALISA
TE
= NU UR = NU
MA
MC
NU S P F NOM =
Forme imbriquée SQL-92!
: ‘Spielberg’
C NUMS = NUMS
PR
SELECT NOM, VILLE
FROM CINÉMA NO E
M TR
TI
WHERE NUMC IN (
SELECT NUMC
FROM SALLE Res
GROUP BY NUMC
HAVING AVG (TAILLE_ÉCRAN) > 40 ) Forme imbriquée SQL-89 :
SELECT DISTINCT C.NOM, F.TITRE
Requête!17!: Quels sont les cinémas Parisiens de la Fox, avec le film FROM CINÉMA C, SALLE S, PASSE P, FILM F
correspondant, qui passent un film d'Elia Kazan avant 22 heures WHERE C.COMPAGNIE = ‘Fox’
dans une salle d'au moins 200 places et d'écran de taille supérieure à AND C.VILLE = ‘Paris’
30!m carrés. AND C.NUMC = S.NUMC
AND S.NBPLACES >= 200
Forme plate :
AND S.TAILLE_ÉCRAN > 30
SELECT DISTINCT C.NOM, F.TITRE
AND S.NUMC = P.NUMC
FROM CINÉMA C, SALLE S, PASSE P, FILM F, PERSONNE P
AND S.NUMS = P.NUMS
WHERE C.COMPAGNIE = ‘Fox’
AND P.HORAIRE < ’22!:00’
AND C.VILLE = ‘Paris’
AND P.NUMF = F.NUMF

Corrigé du TD SQL (BD-Filmographie) 6


AND F.RÉALISATEUR IN ( Graphe de la requête :
SELECT NUMP
FROM PERSONNE
WHERE PRÉNOM = ‘Elia’
COMPAGNIE =
AND NOM = ‘Kazan’ ) NUMF = NUMF
NUMC = NUMC ‘Fox’

Forme imbriquée SQL-92!: F P C


SELECT DISTINCT C.NOM, F.TITRE
FROM CINÉMA C, FILM F

N
U
M
WHERE C.COMPAGNIE = ‘Fox’

F,
TI
TR
AND C.VILLE = ‘Paris’

E
AND (C.NUMC, F.NUMF) IN (
SELECT S.NUMC, P.NUMF
FROM SALLE S, PASSE P Res
WHERE S.NBPLACES >= 200
AND S.TAILLE_ÉCRAN > 30 Forme imbriquée 1 – prédicat IN : pour trouver ceux qui passent dans un cinéma
AND S.NUMC = P.NUMC de la Fox
AND S.NUMS = P.NUMS SELECT DISTINCT NUMF, TITRE
AND P.HORAIRE < ’22!:00’ ) FROM FILM
AND F.RÉALISATEUR IN ( WHERE NUMF IN (
SELECT NUMP SELECT NUMF
FROM PERSONNE FROM PASSE
WHERE PRÉNOM = ‘Elia’ WHERE NUMC IN (
AND NOM = ‘Kazan’ ) SELECT NUMC
FROM CINÉMA
WHERE COMPAGNIE = ‘Fox’ ) )
Requête!18!: Trouver le titre des films qui ne passent à aucun cinéma de la
compagnie FOX. Forme imbriquée 2 – prédicat EXISTS : toujours pour trouver ceux qui passent
On commence par poser la requête inverse!: les films qui passent dans un (au dans un cinéma de la Fox
moins) cinéma de la Fox. SELECT DISTINCT NUMF, TITRE
FROM FILM F
Forme plate : pour trouver ceux qui passent dans un cinéma de la Fox WHERE EXISTS (
SELECT DISTINCT F.NUMF, F.TITRE SELECT *
FROM FILM F, PASSE P, CINÉMA C FROM PASSE P
WHERE F.NUMF = P.NUMF WHERE P.NUMF = F.NUMF
AND P.NUMC = C.NUMC AND EXISTS (
AND C.COMPAGNIE = ‘Fox’

Corrigé du TD SQL (BD-Filmographie) 7


SELECT * Forme 3 – prédicat NOT EXISTS uniquement :
FROM CINÉMA C SELECT DISTINCT NUMF, TITRE
WHERE C.NUMC = P.NUMC FROM FILM F
AND COMPAGNIE = ‘Fox’ ) ) WHERE NOT EXISTS (
La négation de ces deux dernières formes permet d’exprimer la requête initiale!: les SELECT *
films qui ne passent à aucun des cinémas de la Fox. FROM PASSE P, CINÉMA C
WHERE F.NUMF = P.NUMF
Forme imbriquée 1 – prédicat NOT IN : pour trouver ceux qui ne passent dans AND P.NUMC = C.NUMC
aucun cinéma de la Fox AND COMPAGNIE = ‘Fox’ )
SELECT DISTINCT NUMF, TITRE
Si on est très pointilleux, on peut remarquer que la question «!qui ne passent à
FROM FILM
aucun!» peut être comprise comme ne devant retourner que les films actuellement
WHERE NUMF NOT IN ( programmés, mais pas dans un cinéma de la Fox. Si la relation FILM comporte
SELECT NUMF tous les films qui ont été programmés, on peut modifier la requête comme suit!:
FROM PASSE
WHERE NUMC IN ( Forme complète :
SELECT NUMC SELECT DISTINCT NUMF, TITRE
FROM CINÉMA FROM FILM F
WHERE COMPAGNIE = ‘Fox’ ) ) WHERE NUMF IN (
SELECT NUMF
Forme imbriquée 2 – prédicat NOT EXISTS : pour trouver ceux qui ne passent FROM PASSE )
dans aucun cinéma de la Fox AND NOT EXISTS (
SELECT DISTINCT NUMF, TITRE SELECT *
FROM FILM F FROM PASSE P, CINÉMA C
WHERE NOT EXISTS ( WHERE F.NUMF = P.NUMF
SELECT * AND P.NUMC = C.NUMC
FROM PASSE P AND COMPAGNIE = ‘Fox’ )
WHERE P.NUMF = F.NUMF
AND EXISTS (
Requête!19!: Trouver le nom et le prénom des acteurs qui ont eu un salaire plus
SELECT * important dans un film particulier que le salaire du réalisateur du
FROM CINÉMA C même film.
WHERE C.NUMC = P.NUMC
En supposant pour simplifier que les acteurs n’ont joué qu’un seul rôle dans le film.
AND COMPAGNIE = ‘Fox’ ) )
Pour finalement arriver à la forme la plus simple, où seul le prédicat NOT EXISTS Forme plate :
provoque un niveau d’imbrication. SELECT PA.PRÉNOM, PA.NOM
FROM PERSONNE PA, DISTRIBUTION D, FILM F
WHERE PA.NUMP = D.NUMA

Corrigé du TD SQL (BD-Filmographie) 8


AND D.NUMF = F.NUMF WHERE D.NUMF = F.NUMF ) )
AND D.SALAIRE > F.SALAIRE_RÉAL En tenant compte de la possibilité que les acteurs aient joué plusieurs rôles dans le
film, et en supposant qu’ils touchent un salaire pour chaque rôle dans ce cas. (NB!:
Graphe de la requête : cela ne reflète pas forcément les pratiques de l’industrie du cinéma, mais pour
SALAIRE_RÉAL < SALAIRE faire plus proche de la réalité, il faudrait compliquer sensiblement le schéma de la
base).
F D
Forme imbriquée SQL-89 :
NUMF = NUMF
SELECT DISTINCT PA.PRÉNOM, PA.NOM
FROM PERSONNE PA, DISTRIBUTION D

MA
NU
WHERE PA.NUMP = D.NUMA

=
MP
GROUP BY D.NUMA, D.NUMF, PA.PRÉNOM, PA.NOM

NU
P HAVING SUM (SALAIRE) > (
SELECT SALAIRE_RÉAL
PRÉNOM, NOM FROM FILM F
WHERE D.NUMF = F.NUMF ) )
Res Forme imbriquée SQL-92 :
SELECT PRÉNOM, NOM
Forme imbriquée 1 : FROM PERSONNE
SELECT PRÉNOM, NOM WHERE NUMP IN (
FROM PERSONNE SELECT NUMA
WHERE NUMP IN ( FROM DISTRIBUTION D
SELECT D.NUMA GROUP BY NUMA, NUMF
FROM DISTRIBUTION D, FILM F HAVING SUM (SALAIRE) > (
WHERE D.NUMF = F.NUMF SELECT SALAIRE_RÉAL
AND D.SALAIRE > F.SALAIRE_RÉAL ) FROM FILM F
WHERE D.NUMF = F.NUMF ) )
Forme imbriquée 2!:
SELECT PRÉNOM, NOM Requêtes difficiles
FROM PERSONNE
WHERE NUMP IN (
Requête!20!: Trouver les couples acteur-réalisateur (noms et prénoms) tels que
SELECT NUMA l’un a dirigé l’autre sur un film et vice-versa sur un autre.
FROM DISTRIBUTION D
WHERE D.SALAIRE > ( Forme plate :
SELECT F.SALAIRE_RÉAL SELECT DISTINCT P1.PRÉNOM, P1.NOM, P2.PRÉNOM, P2.NOM
FROM FILM F FROM PERSONNE P1, PERSONNE P2, FILM F1, FILM F2,

Corrigé du TD SQL (BD-Filmographie) 9


DISTRIBUTION D1, DISTRIBUTION D2 -- DANS UN SEUL ORDRE
WHERE P1.NUMP > P2.NUMP -- ÉLIMINER LE CAS DES RÉALISATEURS QUI ONT JOUÉ
-- PERMET D’ÉLIMINER DEUX PROBLÈMES!: -- DANS LEUR PROPRE FILM
-- LISTER UN COUPLE (P1, P2) UNE SEULE FOIS AND F1.NUMF = D1.NUMF
-- DANS UN SEUL ORDRE AND D1.NUMA = F2.RÉALISATEUR
-- ÉLIMINER LE CAS DES RÉALISATEURS QUI ONT JOUÉ AND F2.NUMF = D2.NUMF
-- DANS LEUR PROPRE FILM AND D2.NUMA = F1.RÉALISATEUR )
AND P1.NUMP = F1.RÉALISATEUR
AND P2.NUMP = F2.RÉALISATEUR Requête!21!: Trouver le nom, le prénom, le numéro des acteurs qui ont joué dans
AND F1.NUMF = D1.NUMF tous les films de Lelouch, s'il y en a.
AND D1.NUMA = F2.RÉALISATEUR On peut rephraser logiquement cette requête en remarquant que l’on cherche les
AND F2.NUMF = D2.NUMF acteurs des films de Lelouch pour lesquels pour chaque film de Lelouch on peut
AND D2.NUMA = F1.RÉALISATEUR trouver un tuple dans distribution qui indique que l’acteur a bien joué dans ce film.
{acteur!: " film-de-Lelouch, $ distribution tq acteur-a-joué-dans-film }
Graphe de la requête :
RÉA
SQL ne comporte pas d’équivalent du quantificateur universel ". On doit donc
L ISAT EUR
NUMF = NUMF EUR AL ISAT NUMF = NUMF utiliser une transformation logique – introduction d’une double négation – qui
= NU
MA A = RÉ
D1 F1 NUM F1 D1 produit la négation d’un quantificateur existentiel ÿ$ après descente d’une des
NUMP > NUMP
deux négations.
NUMA P1 P1 A
= RÉA = NUM
LISAT
EU R RÉALIS
ATEUR {acteur!: ÿ$ film-de-Lelouch, ÿ$ distribution tq acteur-a-joué-dans-film }
NUMA = NU P = NUMA
MP NUM Le plus simple est de d’abord écrire la requête sans négation en utilisant une forme
imbriquée avec des prédicats EXIXTS, puis d’introduire une double négation. On
PRÉNOM, PRÉNOM,
NOM NOM commencera donc par chercher le nom, le prénom, le numéro des acteurs qui ont
joué dans un des films de Lelouch.
Res
Forme imbriquée – prédicat EXISTS : «!dans un des films!»
Forme imbriquée SQL-92!: SELECT NOM, PRÉNOM
SELECT DISTINCT P1.PRÉNOM, P1.NOM, P2.PRÉNOM, P2.NOM FROM PERSONNE P
FROM PERSONNE P1, PERSONNE P2 WHERE EXISTS (
WHERE (P1.NUMP, P2.NUMP) IN ( SELECT *
SELECT F1.RÉALISATEUR, F2.RÉALISATEUR FROM FILM F
FROM FILM F1, FILM F2, DISTRIBUTION D1, WHERE RÉALISATEUR IN (
DISTRIBUTION D2 SELECT NUMP
WHERE F1.RÉALISATEUR > F2.RÉALISATEUR FROM PERSONNE
-- PERMET D’ÉLIMINER DEUX PROBLÈMES!: WHERE NOM = ‘Lelouch’ )
-- LISTER UN COUPLE (RÉAL1, RÉAL2) UNE SEULE FOIS AND EXISTS (

Corrigé du TD SQL (BD-Filmographie) 10


SELECT * { film,!acteur!: film Œ film-de-Bergman, acteur Œ acteur-ayant-joué-dans-ce-
FROM DISTRIBUTION D film, ÿ$ autre-acteur-ayant-joué-dans-ce-film ÿ$ distribution tq acteur-a-joué-
WHERE D.NUMF = F.NUMF dans-film-avec-plus-gros-salaire-que-autre-acteur }
AND D.NUMA = P.NUMP ) )
Forme imbriquée – prédicat NOT EXISTS : un seul rôle par acteur
Il ne reste plus alors qu’à introduire les deux négations pour obtenir la requête SELECT F.TITRE, PA.PRÉNOM, PA.NOM
souhaitée. FROM FILM F, DISTRIBUTION D1, PERSONNE PA
WHERE F.NUMF = D1.NUMF
Forme imbriquée – prédicat NOT EXISTS : «!dans tous les films!»
AND D1.NUMA = PA.NUMP
SELECT NOM, PRÉNOM, NUMP
AND RÉALISATEUR IN (
FROM PERSONNE P
SELECT NUMP
WHERE NOT EXISTS (
FROM PERSONNE
SELECT *
WHERE NOM = ‘Bergman’ )
FROM FILM F
AND NOT EXISTS (
WHERE RÉALISATEUR IN (
SELECT *
SELECT NUMP
FROM DISTRIBUTION D2
FROM PERSONNE
WHERE D2.NUMF = D1.NUMF
WHERE NOM = ‘Lelouch’ )
AND D2.SALAIRE > D1.SALAIRE )
AND NOT EXISTS (
SELECT * En tenant compte maintenant de la possibilité pour un acteur de jouer plusieurs
FROM DISTRIBUTION D rôles dans un film, on obtient la requête suivante.
WHERE D.NUMF = F.NUMF
Forme imbriquée SQL-89+ – prédicat > ALL : possibilité de plusieurs rôles pour
AND D.NUMA = P.NUMP ) )
un même acteur
SELECT F.TITRE, PA.PRÉNOM, PA.NOM
Requête!22!: Pour chaque film de Bergman, trouver le nom et le prénom de FROM FILM F, DISTRIBUTION D1, PERSONNE PA
l'acteur qui a eu le plus gros salaire. WHERE F.NUMF = D1.NUMF
Il faut également rephraser cette requête pour l’exprimer de façon logique. La AND D1.NUMA = PA.NUMP
requête consiste à chercher les acteurs pour lesquels, quels que soient les autres AND RÉALISATEUR IN (
acteurs du même film, leur salaire est plus élevé. SELECT NUMP
Pour simplifier on va d’abord se limiter au cas où un acteur ne joue qu’un rôle par FROM PERSONNE
film. WHERE NOM = ‘Bergman’ )
{ film,!acteur!: film Œ film-de-Bergman, acteur Œ acteur-ayant-joué-dans-ce- GROUP BY D1.NUMF, D1.NUMA, F.TITRE, PA.PRÉNOM, PA.NOM
film, " autre-acteur-ayant-joué-dans-ce-film $ distribution tq acteur-a-joué- HAVING SUM (SALAIRE) > ALL (
dans-film-avec-plus-gros-salaire-que-autre-acteur } SELECT SUM (SALAIRE)
Soit après introduction d’une double négation pour éliminer le!" : FROM DISTRIBUTION D2
WHERE D2.NUMF = D1.NUMF

Corrigé du TD SQL (BD-Filmographie) 11


AND D2.NUMA <> D1.NUMA WHERE F.NUMF = D1.NUMF
GROUP BY D2.NUMA ) AND D1.NUMA = PA.NUMP
AND RÉALISATEUR IN (
Forme imbriquée SQL-92 : possibilité de plusieurs rôles pour un même acteur SELECT NUMP
SELECT F.TITRE, PA.PRÉNOM, PA.NOM FROM PERSONNE
FROM FILM F, PERSONNE PA WHERE NOM = ‘Bergman’ )
AND NOT EXISTS (
WHERE (F.NUMF, PA.NUMP) IN ( SELECT *
SELECT D1.NUMF, D1.NUMA FROM SALAIRE_TOTAL_ACTEUR_FILM D2
FROM DISTRIBUTION D1 WHERE D2.NUMF = D1.NUMF
WHERE D1.NUMF IN ( AND D2.SALAIRE_TOTAL > D1.SALAIRE_TOTAL )
SELECT NUMF
FROM FILM
Requête!23!: Donner le nom et le prénom des réalisateurs qui ont eu le plus gros
WHERE RÉALISATEUR IN ( salaire sur un de leurs films (par comparaison avec ceux des
SELECT NUMP acteurs).
FROM PERSONNE
Hypothèse 1!: chaque acteur ne joue qu’un rôle, le réalisateur ne joue pas dans le
WHERE NOM = ‘Bergman’ ) ) film correspondant.
GROUP BY D1.NUMF, D1.NUMA
HAVING SUM (D1.SALAIRE) = ( Forme imbriquée :
SELECT MAX ( SELECT PRÉNOM, NOM
SELECT SUM (D2.SALAIRE) FROM PERSONNE
FROM DISTRIBUTION D2 WHERE NUMP IN (
WHERE D2.NUMF = D1.NUMF SELECT RÉALISATEUR
GROUP BY D2.NUMA ) ) FROM FILM F
On peut aussi simplifier en repartant de la requête valable seulement si un acteur ne WHERE SALAIRE_RÉAL > (
joue qu’un rôle par film et en utilisant une vue groupée à la place de distribution. SELECT MAX (SALAIRE)
FROM DISTRIBUTION D
Utilisation d’une vue groupée SQL-92!: WHERE D.NUMF = F.NUMF ) )
CREATE VIEW SALAIRE_TOTAL_ACTEUR_FILM
Hypothèse 2!: un acteur peut jouer plusieurs rôles, le réalisateur ne joue pas dans le
(NUMA, NUMF, SALAIRE_TOTAL) film correspondant.
AS SELECT NUMA, NUMF, SUM (SALAIRE)
FROM FILM Forme imbriquée :
GROUP BY NUMA, NUMF SELECT PRÉNOM, NOM
FROM PERSONNE
SELECT F.TITRE, PA.PRÉNOM, PA.NOM WHERE NUMP IN (
FROM FILM F, SALAIRE_TOTAL_ACTEUR_FILM D1, PERSONNE PA SELECT RÉALISATEUR

Corrigé du TD SQL (BD-Filmographie) 12


FROM FILM F Requête de difficulté moyenne
WHERE SALAIRE_RÉAL > ALL (
SELECT SUM (SALAIRE) Requête!24!: Donner le titre des films qui ont été primés au moins une fois (y
FROM DISTRIBUTION D compris les récompenses des acteurs jouant dans le film).
WHERE D.NUMF = F.NUMF
GROUP BY NUMA ) ) Forme plate SQL-89 :
SELECT DISTINCT F.TITRE, F.ANNÉE
Hypothèse 3!: Tout acteur – y compris le réalisateur s’il joue dans le film
FROM FILM F, RÉCOMPENSE_FILM RF
correspondant – peut jouer plusieurs rôles.
WHERE F.NUMF = RF.NUMF
Forme imbriquée SQL-92 : UNION
SELECT PRÉNOM, NOM SELECT DISTINCT F.TITRE, F.ANNÉE
FROM PERSONNE FROM FILM F, RÉCOMPENSE_ACTEUR RA
WHERE NUMP IN ( WHERE F.NUMF = RA.NUMF
SELECT RÉALISATEUR
Forme imbriquée SQL-92 :
FROM FILM F
SELECT TITRE, ANNÉE
WHERE SALAIRE_RÉAL
FROM FILM
+(
WHERE NUMF IN (
SELECT SUM (SALAIRE)
SELECT NUMF
FROM DISTRIBUTION D1
FROM RÉCOMPENSE_FILM
WHERE D1.NUMF = F.NUMF
UNION
AND D1.NUMA = F.RÉALISATEUR )
SELECT NUMF
>(
FROM RÉCOMPENSE_ACTEUR )
SELECT MAX (
SELECT SUM (SALAIRE)
Requêtes difficiles
FROM DISTRIBUTION D2
WHERE D2.NUMF = F.NUMF
Requête!25!: Lister les cinémas qui ont exclusivement passé des films primés.
GROUP BY D2.NUMA ) ) )
Il faut rephraser cette requête pour l’exprimer de façon logique. La requête consiste
Schéma complémentaire à chercher les cinémas pour lesquels, quels que soient les films programmés, ces
films ont obtenu au moins une récompense. Comme on ne peut pas utiliser d’union
RÉCOMPENSE (NUMR, CATÉGORIE, FESTIVAL) dans une sous-requête, il faut donc utiliser une disjonction (ou).
RÉCOMPENSE_FILM (NUMF, ANNÉE, NUMR)
RÉCOMPENSE_ACTEUR (NUMA, NUMF, ANNÉE, NUMR) { cinéma!: " film-programmé-dans-ce-cinéma ( ($ récompense-film tq film-a-
été-récompensé) ⁄ ($ récompense-acteur tq film-a-été-récompensé) ) }
Pour répondre aux questions suivantes, il faut noter que lorsqu'un acteur reçoit une Soit, après introduction d’une double négation pour éliminer le!", la disjonction se
récompense, le film en reçoit une indirectement. Ce schéma complémentaire transforme en conjonction (et) :
conduit à utiliser une union dans les requêtes.

Corrigé du TD SQL (BD-Filmographie) 13


{ cinéma!: ÿ$ film-programmé-dans-ce-cinéma ( (ÿ$ récompense-film tq film- WHERE R.NUMF = P.NUMF ) )
a-été-récompensé) Ÿ (ÿ$ récompense-acteur tq film-a-été-récompensé) ) }
Forme imbriquée SQL-92 – prédicat NOT IN :
Forme imbriquée SQL-89 : SELECT NOM, VILLE
SELECT NOM, VILLE FROM CINÉMA
FROM CINÉMA C WHERE NUMC NOT IN (
WHERE NOT EXISTS ( SELECT NUMC
SELECT * FROM PASSE
FROM PASSE P WHERE NUMF NOT IN (
WHERE P.NUMC = C.NUMC SELECT R.NUMF
AND NOT EXISTS ( FROM (
SELECT * SELECT NUMF
FROM RÉCOMPENSE_FILM RF FROM RÉCOMPENSE_FILM
WHERE RF.NUMF = P.NUMF ) UNION
AND NOT EXISTS ( SELECT NUMF
SELECT * FROM RÉCOMPENSE_ACTEUR ) AS R ) ) )
FROM RÉCOMPENSE_ACTEUR RA
WHERE RA.NUMF = P.NUMF ) ) Requête!26!: Donner le titre des films qui ont reçu au moins trois récompenses.
En SQL-2 par contre, on peut utiliser une union dans une sous-requête, ce qui
simplifie son expression. Forme imbriquée SQL-92 :
SELECT TITRE, ANNÉE
Forme imbriquée SQL-92 – prédicat NOT EXISTS : FROM FILM
SELECT NOM, VILLE WHERE NUMF IN (
FROM CINÉMA C SELECT R.NUMF
WHERE NOT EXISTS ( FROM (
SELECT * SELECT NUMF
FROM PASSE P FROM RÉCOMPENSE_FILM
WHERE P.NUMC = C.NUMC UNION
AND NOT EXISTS ( SELECT NUMF
SELECT * FROM RÉCOMPENSE_ACTEUR ) AS R
FROM ( GROUP BY R.NUMF
SELECT NUMF HAVING COUNT (*) >= 3 )
FROM RÉCOMPENSE_FILM
UNION
SELECT NUMF
FROM RÉCOMPENSE_ACTEUR ) AS R

Corrigé du TD SQL (BD-Filmographie) 14


Requête!27!: Noms et prénoms des acteurs qui ont reçu plus de récompenses
qu'aucun acteur qui a joué dans "Casablanca" n'en a eu.

Forme imbriquée SQL-92 :


SELECT PRÉNOM, NOM
FROM PERSONNE
WHERE NUMP IN (
SELECT NUMA
FROM RÉCOMPENSE_ACTEUR
GROUP BY NUMA
HAVING COUNT (*) > (
SELECT MAX (
SELECT COUNT (*)
FROM RÉCOMPENSE_ACTEUR
WHERE NUMA IN (
SELECT NUMA
FROM DISTRIBUTION
WHERE NUMF IN (
SELECT NUMF
FROM FILM
WHERE TITRE = ‘Casablanca’ ) )
GROUP BY NUMA ) ) )

Corrigé du TD SQL (BD-Filmographie) 15

Vous aimerez peut-être aussi