Académique Documents
Professionnel Documents
Culture Documents
TD 3 2016-2017
Aujourd’hui, nous allons utiliser un autre schéma, le schéma sakila qui contient des
informations utilisées par un magasin de location de DVD. Le schéma est visible sur Moodle
(Sciences / UFR de math / Master ISIFAR / BD ). Vous pouvez aussi inspecter les tables
comme d’habitude avec
bd_2017=# \d sakila.film
bd_2017=# \d sakila.actor
Pour connaı̂tre les acteurs qui ont joué dans au moins un film, on pourra écrire :
SELECT ∗ FROM s a k i l a . a c t o r AS ac
WHERE EXISTS (SELECT ∗
FROM s a k i l a . f i l m a c t o r a s f a
WHERE f a . a c t o r i d = ac . a c t o r i d ) ;
On peut utiliser cette requête pour trouver les pays qui n’ont pas de langue officielle par
exemple :
SELECT ∗ FROM world . c o u n t r y a s p
LEFT JOIN world . c o u n t r y l a n g u a g e a s l
ON p . c o u n t r y c o d e = l . c o u n t r y c o d e AND l . i s o f f i c i a l
WHERE l . c o u n t r y c o d e IS NULL;
1
Base de données L3 MIASHS-M1 ISIFAR
TD 3 2016-2017
2 Exercices
2.1 Requêtes
1. Quels sont les langues qui ne sont officielles dans aucun pays ? Écrivez une version avec
NOT IN et une autre avec LEFT JOIN.
Deuxième version :
SELECT l 1 . l a n g u a g e FROM c o u n t r y l a n g u a g e a s l 1
LEFT JOIN c o u n t r y l a n g u a g e a s l
ON ( l 1 . l a n g u a g e = l . l a n g u a g e and l . i s o f f i c i a l )
WHERE l . l a n g u a g e IS NULL;
Troisième version :
SELECT l a n g u a g e FROM c o u n t r y l a n g u a g e c l
WHERE NOT EXISTS
(SELECT ”l a n g u a g e ” FROM c o u n t r y l a n g u a g e c l 1
WHERE c l 1 . l a n g u a g e=c l . l a n g u a g e AND
cl1 . i s o f f i c i a l ) ;
En calcul relationnel
n
l.language :countrylanguage(l)∧
¬ ∃t countrylanguage(t)∧
o
l.language = t.language ∧ t.isofficial
2
Base de données L3 MIASHS-M1 ISIFAR
TD 3 2016-2017
En calcul relationnel
n
f.title :film(f )∧
¬ ∃t, t1 inventory(t) ∧ ∃t1 rental(t1 )∧
o
f.film_id = t.film_id ∧ t.inventory_id = t1 .inventory_id
Solution:
WITH ActCat AS (SELECT a c t o r i d , c a t e g o r y i d FROM s a k i l a . f i l m a c t o r
NATURAL JOIN s a k i l a . f i l m c a t e g o r y ) ,
ActNot AS (SELECT a c t o r i d FROM s a k i l a . a c t o r , s a k i l a . c a t e g o r y
WHERE ( a c t o r i d , c a t e g o r y i d ) NOT IN (SELECT ∗ FROM ActCat ) ) ,
ActId AS (SELECT a c t o r i d FROM s a k i l a . a c t o r
EXCEPT SELECT ∗ FROM ActNot )
Solution:
WITH Copain AS
(SELECT R1 . a c t o r i d FROM s a k i l a . f i l m a c t o r a s R1
JOIN s a k i l a . f i l m a c t o r a s R2
ON (R1 . f i l m i d = R2 . f i l m i d AND R1 . a c t o r i d != R2 . a c t o r i d )
)
3
Base de données L3 MIASHS-M1 ISIFAR
TD 3 2016-2017
SELECT a c t o r i d FROM s a k i l a . a c t o r
WHERE a c t o r i d not i n (SELECT ∗ FROM Copain ) ;
5. Nom, prénom des clients installés dans des villes sans magasins ?
Solution:
WITH CustomerCity AS
(SELECT f i r s t n a m e , l a s t n a m e , c u s t o m e r i d , c i t y i d
FROM s a k i l a . customer NATURAL JOIN s a k i l a . a d d r e s s ) ,
S t o r e C i t y AS
(SELECT c i t y i d FROM s a k i l a . s t o r e NATURAL JOIN s a k i l a . a d d r e s s )
6. Lister les pays pour lesquels toutes les villes ont au moins un magasin.
Solution: Chaque fois qu’on lit dans la questions « tous » ou « toutes », on est
tenté de voir une division. Ici ce n’est pas le cas. Il faut d’abord déterminer les
villes sans magasins, puis leur pays et retirer ces pays de la liste de tous les pays.
WITH c i t y w i t h o u t s t o r e AS (
SELECT c i t y i d FROM s a k i l a . c i t y
EXCEPT
SELECT DISTINCT c . c i t y i d
FROM s a k i l a . s t o r e NATURAL JOIN s a k i l a . a d d r e s s
NATURAL JOIN s a k i l a . c i t y c
)
SELECT ∗ FROM s a k i l a . c o u n t r y co
WHERE NOT EXISTS (SELECT ∗ FROM
s a k i l a . c o u n t r y NATURAL JOIN c i t y w i t h o u t s t o r e ) ;
4
Base de données L3 MIASHS-M1 ISIFAR
TD 3 2016-2017
Solution:
CREATE OR REPLACE FUNCTION e n t i d . f i l m i d c a t ( s t e x t )
RETURNS TABLE( f i l m i d s m a l l i n t ) LANGUAGE s q l
AS $$
SELECT f i l m i d FROM f i l m c a t e g o r y NATURAL JOIN c a t e g o r y
WHERE c a t e g o r y . name=s ;
$$ ;
Solution:
SELECT DISTINCT ac . ∗ FROM s a k i l a . a c t o r ac
NATURAL JOIN
(SELECT ∗ FROM s a k i l a . f i l m a c t o r
WHERE f i l m i d IN
(SELECT ∗ FROM e n t i d . f i l m i d c a t ( ’ Horror ’ )
)
) fa ;
ou
SELECT DISTINCT ac . ∗
FROM s a k i l a . a c t o r ac NATURAL JOIN
s a k i l a . f i l m a c t o r NATURAL JOIN
e n t i d . f i l m i d c a t ( ’ Horror ’ ) ;
2. Quels sont les acteur qui n’ont jamais joué dans une comédie (’Comedy’) ?
Solution:
Attention ! Cette requête ne répond pas à la question :
SELECT DISTINCT ac . ∗
FROM s a k i l a . a c t o r ac NATURAL JOIN
(SELECT ∗ FROM s a k i l a . f i l m a c t o r
WHERE f i l m i d NOT IN
(SELECT ∗ FROM e n t i d . f i l m i d c a t ( ’ Comedy ’ )
)
) fa ;
5
Base de données L3 MIASHS-M1 ISIFAR
TD 3 2016-2017
Elle répond à la question : Quels sont les acteur qui ont joué dans un film qui n’est
pas une comédie ?
Une réponse correcte est
SELECT DISTINCT ac . l a s t n a m e , a c f i r s t n a m e
FROM s a k i l a . a c t o r ac
WHERE NOT EXISTS
(SELECT ∗ FROM s a k i l a . f i l m a c t o r f a
WHERE f i l m i d IN
(SELECT ∗ FROM e n t i d . f i l m i d c a t ( ’ Comedy ’ ) )
AND f a . a c t o r i d = ac . a c t o r i d
) ;
3. Quels sont les acteurs qui ont joué dans un film d’horreur (’Horror’) et dans un film
pour enfant (’Children’) ?
Le résultat est vide et la requête ne correspond pas à la question posée. Elle calcule
les actor_id des acteurs qui ont dans au moins un film qui relève simultanément
des catégories Horror et Children (ce genre de film est assez rare).
Pour calculer un résultat correct, il faut pour chaque valeur a de actor_id re-
chercher deux tuples (pas nécessairement distincts) de film_actor où l’attribut
actor_id vaut a et ou dans un cas film_id désigne un film pour enfants et dans
6
Base de données L3 MIASHS-M1 ISIFAR
TD 3 2016-2017
En algèbre relationnelle
πlast_name,first_name actor ./
\
πactor_id (film_actor ./ film_id_cat(’Children’))
πactor_id (film_actor ./ film_id_cat(’Horror’))