Académique Documents
Professionnel Documents
Culture Documents
Version 1.0
Alain Taquet
Septembre 2017
Table des matières
i
3.5 Non existence d’associations . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4 CM4 : Jointures 22
4.1 Jointure croisée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.2 Jointure interne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2.1 Avec condition de selection . . . . . . . . . . . . . . . . . . . . . . . 23
4.2.2 Auto-jointures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2.3 Sous requêtes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2.4 Jointures généralisées . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.3 Opérateurs de jointure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.4 Jointure externe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.5 Utilité de la jointure croisée . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5 CM5 : Regroupements 32
5.1 La clause GROUP BY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.2 Sémantique du GROUP BY . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.3 GROUP BY HAVING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
5.4 Groupement avec jointure externe . . . . . . . . . . . . . . . . . . . . . . . . 38
6 CM6 : Exercices 39
6.1 Quelques précisions sur null et IN . . . . . . . . . . . . . . . . . . . . . . . . 39
6.2 La base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
6.3 Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
9 TD4 : Jointures 51
10 TD5 : Regroupements 54
11 TD6 : Synthèse 57
12 Cinema1 60
12.1 La base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
12.2 Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
13 Cinema2 63
13.1 Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
14 Cinema3 67
14.1 Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
ii
19 Correction TD5 : Regroupements 92
iii
CHAPITRE 1
1.1 Cardinalités
1.2.1 Description
Des personnes habitent une et une seule ville localisée dans une et une seule région. Ces per-
sonnes sont recrutées pour effectuer des interventions dans plusieurs régions (qui ne sont pas
nécessairement les régions où ils habitent). Les personnes peuvent avoir un responsable, leur
salaire se trouve dans une tranche (min, max) indiquée dans la table tranche.
1.2.2 Relations
La création d’une table se fait à l’aide de la commande CREATE TABLE suivi du nom de la
table.
1
Bases de Données MIASHS, Version 1.0
On doit placer ensuite entre parenthèses les noms des colonnes suivi du type de données, chaque
colonne étant séparée par une virgule. Nous n’utiliserons pour l’instant que les types TEXT et
INTEGER
Les clés primaires sont indiquées avec PRIMARY KEY(“champ”), s’il y a plusieurs champs
on écrit PRIMARY KEY(“champ1”, “champ2”)
Les clés étrangères sont notées FOREIGN KEY (“champ”) REFERENCES “table”
(“champ”)
Si la valeur d’une colonne ne peut pas être null on ajoute après le type la contrainte NOT
NULL
On insère une ligne dans une table avec la commande INSERT INTO table VALUES (val1,
val2, ... ) ;
On supprime une ligne avec la commande DELETE FROM table WHERE condition ;
(champ=val)
On modifie une valeur avec UPDATE table SET champ = val WHERE condition ;
- Table regions
# coderegion region
1 1 nord
2 2 sud
3 3 centre
4 4 corse
- Table villes
);
# codepersonne coderegion
1 1 1
2 1 3
3 2 1
4 3 2
5 4 2
6 1 2
7 1 4
- Table salaires
Les requêtes présentées ici extraient des valeurs d’une seule table en ignorant totalement les
autres tables de la base.
La clause SELECT indique les valeurs à obtenir pour chaque ligne, le FROM indique la table
à utiliser pour obtenir ces résultats et le WHERE les conditions à remplir par les valeurs. Les
lignes peuvent être triées avec la clause ORDER BY.
Les valeurs obtenues peuvent être les valeurs d’un champ de la table mais peuvent ausi être
calculées au moyen d’expressions ou de fonctions portant sur plusieurs champs d’une même
ligne.
La clause select produit une table qui peut être le résultat demandé mais qui peut aussi servir de
point de départ à une autre clause select, on obtiendra alors des sous requêtes vues au chapitre
suivant.
La base exemple avec laquelle nous allons travailler se trouve ici : exemple.s3db et est
décrite au chapitre précédent.
La clause SELECT indique les valeurs qui constituent chaque ligne du résultat. Le FROM
indique la ou les tables utilisées.
SELECT x, y
FROM T;
On peut également préfixer les noms des champs par le nom de la table : T.x Ce sera très
important dans les prochains chapitres lorsque des champs de plusieurs tables auront le même
nom.
5
Bases de Données MIASHS, Version 1.0
2.1.1 Projection
# nom salaire
1 Amelmou 30000
2 Alavie 20000
3 Ancieux 15000
4 Tete 40000
L’étoile (*) permet de sélectionner tous les champs des tables du FROM :
- Afficher tous les champs de la table villes.
SELECT *
FROM villes;
SELECT codepostal
FROM personnes;
# codepostal
1 59000
2 59800
3 26200
4 59000
On remarque que 59000 est affiché 2 fois
On affiche une seule fois les lignes avec DISTINCT :
SELECT DISTINCT x, y
FROM T;
# codepostal
1 59000
2 59800
3 26200
SELECT 1 + 1;
SELECT x AS y
FROM T;
# salarie salaireNet
1 Amelmou 24000.0
2 Alavie 16000.0
3 Ancieux 12000.0
4 Tete 32000.0
La clause WHERE indique les conditions que doivent satisfaire les lignes qui donnent le résul-
tat.
SELECT x, y
FROM T
WHERE conditions;
2.2.1 Filtrage
SELECT nom
FROM personnes
WHERE salaire > 15000;
# nom
1 Amelmou
2 Alavie
3 Tete
On peut utiliser les opérateurs de comparaison usuels : =, ==, <, >, >=, <=, <> , les opérateurs
logiques : OR, AND, NOT
Attention aux priorités. Ordre : comparaison, puis NOT, puis AND, puis OR.
- Afficher les noms des personnes qui gagnent entre 1000 et 20 000 ou entre 30 000 et 100 000
C
SELECT nom
FROM personnes
WHERE (salaire >= 1000 AND salaire <= 20000)
OR (salaire >= 30000 AND salaire <= 100000);
# nom
1 Amelmou
2 Alavie
3 Ancieux
4 Tete
On peut également utiliser la syntaxe BETWEEN ... AND ... :
SELECT x
FROM T
WHERE y BETWEEN val1 AND val2;
SELECT nom
FROM personnes
WHERE salaire NOT BETWEEN 20000 AND 30000;
# nom
1 Ancieux
2 Tete
SELECT x
FROM T
WHERE y LIKE modele;
- Afficher les nom des personnes dont le nom commence par A et qui ont un ‘u’ avant le dernier
caractère
SELECT nom
FROM personnes
WHERE nom LIKE 'A%u_';
# nom
1 Ancieux
- Afficher les nom des personnes dont le nom possède un ‘e’ mais pas en dernier caractère
SELECT nom
FROM personnes
WHERE nom LIKE '%e%' AND nom NOT LIKE '%e';
# nom
1 Amelmou
2 Ancieux
Les valeurs nulles ne sont pas renseignées, elles contiennent la valeur NULL qui correspond à
“inconnu”. On ne les teste pas avec l’opérateur d’egalité mais avec IS NULL (ou is not null) :
SELECT x
FROM T
WHERE y IS NULL;
SELECT nom
FROM personnes
WHERE responsable IS NULL;
# nom
1 Amelmou
2 Tete
Order by permet de trier les lignes, par défaut les résultats sont dans l’ordre croissant (ASC) on
peut inverser en utilisant DESC après le nom de la colonne :
SELECT x, y
FROM T
ORDER BY x ASC, y DESC;
SELECT nom
FROM personnes
ORDER BY nom;
# nom
1 Alavie
2 Amelmou
3 Ancieux
4 Tete
On peut trier suivant plusieurs critères :
- Afficher les noms des personnes et leur code postal dans l’ordre croissant des codes postaux
et l’ordre inverse des noms
# codepostal nom
1 26200 Ancieux
2 59000 Tete
3 59000 Amelmou
4 59800 Alavie
On peut trier sur des champs calculés :
- Afficher les noms des personnes dans l’ordre croissant des salaires net (même si le tri suivant
le salaire suffirait !)
SELECT nom
FROM personnes
ORDER BY salaire * 0.8;
# nom
1 Ancieux
2 Alavie
3 Amelmou
4 Tete
Si on affiche le champ calculé il est plus simple de mettre un alias et de trier suivant l’alias :
- Afficher les noms et les salaires net des personnes dans l’ordre croissant des salaires net puis
des noms
# nom salaireNet
1 Ancieux 12000.0
2 Alavie 16000.0
3 Amelmou 24000.0
4 Tete 32000.0
Les Fonctions habituelles de texte sont présentes : upper(x), lower(x), concat(x,y), length(x),
substr(x,debut,nb)
SQLite ne supporte pas la fonction concat, il faut utiliser l’opérateur | |
- Afficher les numéros de départements d’où proviennent les personnes
# departement
1 59
2 26
On peut utiliser ces focntions dans n’importe quelle clause :
- Afficher les noms des personnes du département du nord (59) en utilisant substr et pas like.
Le numéro du département se calcule en prenant les 2 premiers caractères du code postal.
SELECT nom
FROM personnes
WHERE substr(codepostal,1,2) = '59';
# nom
1 Amelmou
2 Alavie
3 Tete
On peut combiner des fonctions :
- Afficher le nom des personnes avec la première lettre en majuscule, et le reste en minuscule
# Nom
1 Amelmou
2 Alavie
3 Ancieux
4 Tete
La commande CASE ... WHEN ... permet d’utiliser des conditions de type si/sinon comme
dans les langages de programmation. On peut l’utiliser dans n’importe quelle clause (select,
where, order by ou having). Il existe 2 syntaxes :
CASE x
WHEN val1 THEN res1
WHEN val2 THEN res2
ELSE res3
END -- AS y
CASE
WHEN cond1 THEN res1
WHEN cond1 THEN res2
ELSE res3
END -- AS y
- Afficher le nom des personnes et leur ville. Si le code postal est 59000 ou 59800 on affichera
‘Lille’ sinon ‘autre’ :
SELECT nom,
CASE codepostal
WHEN '59000' THEN 'Lille'
WHEN '59800' THEN 'Lille'
ELSE 'autre'
END AS ville
FROM personnes;
# nom ville
1 Amelmou Lille
2 Alavie Lille
3 Ancieux autre
4 Tete Lille
- Même question en utilisant la 2° syntaxe :
SELECT nom,
CASE
WHEN codepostal== '59000' OR codepostal=='59800' THEN 'Lille'
ELSE 'autre'
END AS ville
FROM personnes;
# nom ville
1 Amelmou Lille
2 Alavie Lille
3 Ancieux autre
4 Tete Lille
- Afficher le nom des personnes et leur departement. Si le numéro du departement est 59 on
affichera ‘Nord’ sinon ‘autre’ :
SELECT nom,
CASE substr(codepostal,1,2)
WHEN '59' THEN 'Nord'
ELSE 'autre'
END AS dpt
FROM personnes;
# nom dpt
1 Amelmou Nord
2 Alavie Nord
3 Ancieux autre
4 Tete Nord
- On classe les salariés en 3 groupes suivant leur salaire, s’ils gagnent au moins 30 000 C il
seront dans la tranche 1, au moins 20 000 pour la tranche 2 sinon la tranche 3. Afficher les
noms des salariés ainsi que la tranche dans laquelle ils sont classés.
SELECT nom,
CASE
WHEN salaire >= 30000 THEN "tranche1"
WHEN salaire >= 20000 THEN "tranche2"
ELSE "tranche3"
END AS tranche
FROM personnes
ORDER BY tranche, nom;
# nom tranche
1 Amelmou tranche1
2 Tete tranche1
3 Alavie tranche2
4 Ancieux tranche3
La valeur Null n’est pas une valeur, c’est un marqueur qui indique l’absence de valeur. On ne
peut donc pas écrire dans une condition x = null ni x + null. Pouvoir remplacer un marqueur
null par une chaine vide, la valeur 0, etc.. est très utile.
On peut bien sûr utiliser le case when :
– Afficher le nom des personnes et le numéro de leur responsable. S’ils n’ont pas de respon-
sable on affichera “Directeur”
SELECT nom,
CASE
WHEN responsable IS NULL THEN "Directeur"
ELSE responsable
END AS responsable
FROM personnes
# nom responsable
1 Amelmou Directeur
2 Alavie 1
3 Ancieux 4
4 Tete Directeur
Attention à l’erreur suivante : NULL n’est pas une valeur
SELECT nom,
CASE responsable
WHEN NULL THEN "Directeur" -- ERREUR
ELSE responsable
END AS responsable
FROM personnes
# nom responsable
1 Amelmou
2 Alavie 1
3 Ancieux 4
4 Tete
La fonction cooalesce(x, val1, val2, ...) permet de remplacer la valeur Null par la pemière valeur
non null
La requête précédente s’écrit donc plus simplement :
Les fonctions statistiques calculent des valeurs calculées sur l’ensemble des lignes. On trouve
les fonctions habituelles count, avg (moyenne), sum, min, max
- Calculer le nombre de personnes, la moyenne et l’écart des salaires des personnes.
- On peut effectuer des calculs sur les champs : calculer la moyenne des salaires nets
# moysalaire
1 21000.0
La fonction count retourne le nombre de lignes mais ce n’est pas toujours ce que l’on veut
obtenir :
- calculer le nombre de regions ou interviennent des personnes
SELECT count(coderegion) as nb
FROM interventions;
# nb
1 7
Le résultat donne 7 alors qu’il n’y a que 4 régions dans la base.
On compte les valeurs non dupliquées avec COUNT(DISTINCT ...)
# nb
1 4
Cas particulier de NULL : null n’est pas une valeur donc n’est pas totalisée avec un count, par
contre 0 + null donne null.
- Calculer le nombre de personnes sans responsables
# nbdirecteurs
1 2
- Calculer le nombre de personnes et le maximum des salaires qui ont pour nom “personne”
# nbpers maxsal
1 0
On trouve 0 pour nbpers et null pour maxsal
Les requêtes présentées ici extraient encore des valeurs sur une seule table mais les lignes sont
sélectionnées en fonction de l’existence possible ou non d’une association à des lignes d’autres
tables.
On a vu au chapitre précédent qu’une requête SELECT produisait une table, il est possible
d’utiliser le résultat d’un SELECT comme point de départ d’une autre requête. On peut ainsi
imbriquer autant de requêtes que l’on veut, le résultat de la requête la plus imbriquée servant
de point de départ à la requête du niveau immédiatement supérieur.
Les sous requêtes peuvent dépendre du contexte dans lequel elles sont exécutées, donc des
requêtes englobantes, on parlera alors de corrélation entre requêtes. Une ou des valeurs des
requêtes imbriquées dépendent alors des requêtes englobantes.
Pour executer une requete il est necessaire de creer une sous requete qui donne un resultat
intermédiaire utilisé dans une requête englobante
Si la sous requête retourne plusieurs valeurs on utilise IN, si elle ne retourne qu’une seule
valeur on peut utiliser l’opérateur =
On se propose d’afficher les noms des personnes de Lille. Il faut tout d’abord déterminer les
codes postaux de lille puis chercher les personnes qui ont un code postal correspondant :
- Détermination des codes postaux de lille :
SELECT codepostal
FROM villes
WHERE ville = 'Lille';
16
Bases de Données MIASHS, Version 1.0
# codepostal
1 59000
2 59800
- Affichage des personnes de lille (version 1)
SELECT nom
FROM personnes
WHERE codepostal = '59000' OR codepostal = '59800';
# nom
1 Amelmou
2 Alavie
3 Tete
On peut éviter d’utiliser plusiers fois OR avec l’opérateur IN : IN (val1, val2, ... )
SELECT nom
FROM personnes
WHERE codepostal IN ('59000', '59800');
Puisque la première requête retourne les 2 codes postaux il serait interessant de remplacer ces
2 valeurs par la requete qui permet de les obtenir. La requête peut maintenant se faire en une
seule étape :
SELECT nom
FROM personnes
WHERE codepostal IN (
SELECT codepostal
FROM villes
WHERE ville = 'Lille');
SELECT nom
FROM personnes
WHERE codepostal IN (
SELECT codepostal
FROM villes
WHERE coderegion IN (
SELECT coderegion
FROM regions
WHERE region = 'nord'));
# nom
1 Amelmou
2 Alavie
3 Tete
On peut référencer plusieurs fois la même table dans une requête et une sous requête :
- Quelles sont les villes de la meme region que Lille (ne pas afficher Lille)
# ville
1 Roubaix
Attention à ville référencé 2 fois : une fois dans la sous requête pour obtenir le code de la
région et une autre fois dans la requête principale. Le champ ville de la sous requête n’est pas
visible dans la requête principale, on peut écrire ville = ‘Lille’ ET ville != ‘Lille’ sans qu’il y
ait contradiction.
Lorsqu’une requête retourne une seule valeur il est possible de la comparer comme toutes les
autres valeurs. Les opérateurs vus au précédent chapitre :=, <, >, >=, <=, <> , OR, AND, NOT
peuvent donc s’appliquer.
SELECT x FROM T1
WHERE (SELECT a FROM T2 WHERE b ) operateur y;
- Afficher les noms des personnes qui ont un salaire supérieur ou égal à la moyenne des salaires
# nom
1 Amelmou
2 Tete
Dans les requêtes précédentes les sous requêtes ne voient pas la requête principale, il est pos-
sible pour une sous requête d’utiliser des champs des requêtes sous jacentes. Lorsqu’une table
de la requête principale et une table de la sous requête ont des champs ayant le même nom on
peut prefixer les champs par le nom des tables ou renommer la table de la requête principale.
On renomme une table en indiquant l’alias après le nom de la table. On peut écrire “table AS
T” ou “table T”. Les champs de la table renommée doivent être préfixés : T.x
– Afficher les noms des regions ou interviennent au moins 2 personnes
Pour chaque région ayant pour code coderegion on crée une sous requête qui calcule le nombre
de personnes qui sont intervenues (table interventions) dans la région de même code. La sous
requête extrait les lignes de la table intervention si coderegion (de la table intervention donc de
la sous requête) est égal à coderegion (de la table region donc de la requête principale).
Les deux champs ayant le même nom mais se trouvant dans des tables n’ayant pas le même
nom on les prefixe par le nom de la table.
# region
1 nord
2 sud
– Afficher les noms des clients qui ont un salaire supérieur ou égal à la moyenne du même
département
Pour chaque personne il faut créer une sous requête qui calcule la moyenne des salaires des
personnes du même département puis comparer le salaire de cette personne avec la moyenne
calculée dans la sous requête.
Cette fois on ne peut pas prefixer par la table personnes, il faut donc renommer la table personne
de la requête principale.
# nom
1 Amelmou
2 Ancieux
3 Tete
Attention à l’erreur suivante : ici on renomme la table personnes de la sous requête :
SELECT avg(salaire)
FROM personnes P -- ERREUR
WHERE substr(P.codepostal,1,2) = substr(codepostal,1,2));
# nom
1 Amelmou
2 Tete
Le P.codepostal correspond à codepostal de la sous requête donc la condition ne sert à rien et
on affiche les personnes qui ont un salaire supérieur ou égal à la moyenne des salaires !
# nom
1 Amelmou
Ce type de requête est appelé division, suivant les formes des tables la requête est quelquefois
plus compliquée à écrire.
SELECT nom
FROM personnes
WHERE codepersonne NOT IN (
SELECT codepersonne
FROM interventions
WHERE coderegion = 1);
# nom
1 Ancieux
2 Tete
attention à l’erreur : une personne peut intervenir dans plusieurs régions donc à la fois dans la
région 1 et la région 2
SELECT nom
FROM personnes
WHERE codepersonne IN (
SELECT codepersonne
FROM interventions
WHERE coderegion != 1); -- ERREUR
# nom
1 Amelmou
2 Ancieux
3 Tete
On peut combiner IN et NOT IN :
- regions dans lesquelles n’intervient pas Alavie. On cherche les codes de régions dans les-
quelles intervient Alavie et on affiche les régions qui n’ont pas ces codes.
SELECT region
FROM regions
WHERE coderegion NOT IN (
SELECT coderegion
FROM interventions
WHERE codepersonne = (
SELECT codepersonne
FROM personnes
WHERE nom = 'Alavie'));
# region
1 sud
2 centre
3 corse
CM4 : Jointures
Dans les chapitres précédents les données étaient extraites d’une seule table mais elles se
trouvent souvent réparties dans plusieurs tables. La jointure permet une liaison entre 2 tables et
d’utiliser tous les champs.
On peut distinguer les jointures croisées, les jointures internes et les jointures externes.
Les jointures peuvent s’écrire avec le prédicat JOIN ou dans le WHERE dans le cas des join-
tures internes.
La jointure croisée réalise le produit cartésien (ou produit relationnel) des 2 tables. Chaque
ligne d’une table est mise en relation avec toutes les lignes de l’autre table. Le nombre de
lignes obtenu est égal à card(T1) * card(T2). On crée cette jointure en indiquant le nom des
tables dans le FROM.
SELECT x
FROM T1, T2
# ville nom
1 Lille Amelmou
2 Lille Alavie
X X X
19 Roubaix Ancieux
20 Roubaix Tete
22
Bases de Données MIASHS, Version 1.0
La jointure interne fait correspondre les lignes des 2 tables en fonction d’un prédicat (condition)
portant sur les colonnes des tables. On indique la condition des jointure dans le WHERE comme
pour les conditions de filtrage. On peut considérer qu’il s’agit d’un filtre sur le produit cartésien
des 2 tables. On verra plus loin qu’on peut utiliser l’opérateur JOIN
SELECT x
FROM T1, T2
WHERE T1.a = T2.b;
- Pour chaque ville afficher les noms des personnes qui y habitent. On doit effectuer la jointure
entre les codes postaux des 2 tables, les noms des champs étant identique il faut les prefixer.
# ville nom
1 Lille Amelmou
2 Lille Tete
3 Lille Alavie
4 Montelimar Ancieux
On remarque que Paris et roubaix n’apparaissent pas, personne n’habitant ces 2 villes leur code
postal n’est pas présent dans la table personnes et les lignes ne peuvent pas être liées. Pour
afficher ces villes il faut utiliser une jointure externe.
On peut ajouter des conditions de filtrage comme dans tout SELECT. On les ajoutera avec un
AND.
SELECT x
FROM T1, T2
WHERE T1.a = T2.b
AND conditions;
# ville nom
1 Lille Amelmou
2 Lille Tete
3 Lille Alavie
4.2.2 Auto-jointures
Une table peut être jointe avec elle-même, il faut dans ce cas renommer les tables en indiquant
leur alias après leur nom.
SELECT x
FROM T T1, T T2
WHERE T1.a = T2.b;
- Afficher les villes de la même region que roubaix. Il ne faut pas oublier qu’une ville peut avoir
plusieurs codes postaux.
# ville
1 Lille
Les sous requêtes produisent des tables, on peut donc les utiliser comme les autres tables de
la base et les placer dans le FROM. Dans le chapitre précédent une sous requête produisait un
résultat comparé dans le WHERE, ici on place les sous requêtes dans le FROM et les conditions
de jointure dans le WHERE. Pour nommer la sous requete il suffit d’indiquer son nom après
son code.
SELECT x
FROM T1, (SELECT y FROM T2) ssreq
WHERE T1.y op ssreq.y;
Pour afficher les personnes de la région Lille, le code postal des personnes était comparé au
niveau du WHERE à ceux de Lille.
SELECT nom
FROM personnes
WHERE codepostal IN (
SELECT codepostal FROM villes WHERE ville = 'Lille');
Ici une sous requete produira une table contenant les codes postaux de Lille et en effectuant
une jointure avec la tables personnes on pourra extraire les lignes des personnes de Lille
SELECT nom
FROM personnes,
(SELECT codepostal FROM villes WHERE ville = 'Lille') cpLille
WHERE personnes.codepostal = cpLille.codepostal;
- Afficher les villes de la région de Roubaix avec une sous requête au niveau du WHERE
# ville
1 Lille
- Même question avec une jointure
# ville
1 Lille
Une jointure ne se limite pas à une simple égalité (équi-jointure) on peut utiliser des expres-
sions :
SELECT x
FROM T1, T2
WHERE T1.a = T2.b;
# nom
1 Amelmou
2 Tete
- nom et tranche des salaires des personnes
# nom tranche
1 Amelmou A
2 Alavie B
3 Ancieux C
4 Tete A
SQL2 introduit des opérateurs de jointure. Nous utiliserons dans ce cours les opérateurs de
jointure interne : JOIN et de jointure externe : LEFT JOIN
-- jointure croisée
SELECT T1.x, T2.y
FROM T1 JOIN T2
-- jointure interne
SELECT x
FROM T1 JOIN T2 ON T1.a = T2.b;
# nom region
1 Amelmou nord
2 Alavie nord
3 Ancieux sud
4 Tete nord
- Afficher les noms des personnes de la région nord
SELECT nom
FROM personnes P
JOIN villes V ON P.codepostal = V.codepostal
JOIN regions R ON V.coderegion = R.coderegion
WHERE region = 'nord';
# nom
1 Amelmou
2 Tete
3 Alavie
La jointure externe permet d’afficher des lignes pour lesquelles il n’y a pas correspondance et
qui sont donc éliminées avec une jointure interne. On peut écrire LEFT JOIN ou LEFT OUTER
JOIN
On veut par exemple afficher les régions et les villes des régions, la requête avec une jointure
interne ne fait pas apparaître la région corse :
# region ville
1 nord Lille
2 nord Lille
3 nord Roubaix
4 sud Montelimar
5 centre Paris
Avec une jointure gauche on obtient toutes les régions même si le coderegion de la corse n’ap-
parait pas dans les villes. Toutes les lignes de la table de gauche (avant le join) sont affichées,
si une valeur n’est pas présente dans la table de droite elle est remplacée par null.
# region ville
1 nord Lille
2 nord Lille
3 nord Roubaix
4 sud Montelimar
5 centre Paris
6 corse null
- Afficher le nom de chaque personne et le nom de son responsable s’il y en a un
# P.nom responsable
1 Alavie Amelmou
2 Amelmou
3 Ancieux Tete
4 Tete
Dans cette requete on peut utiliser coalesce
Il est bien sur possible d’utiliser is null :
- Afficher les villes où il n’y a personne
SELECT ville
FROM villes V
LEFT JOIN personnes P ON P.codepostal = V.codepostal
WHERE nom is null;
# ville
1 Paris
2 Roubaix
On peut enchainer les JOIN donc les LEFT JOIN mais attention à la logique de la requête
– Afficher les régions où il n’y a personne.
On peut penser à la requête suivante (fausse) : s’il n’y a personne c’est que le nom de la table
personne doit être null
SELECT region
FROM regions R
LEFT JOIN villes V ON R.coderegion = V .coderegion
LEFT JOIN personnes P ON P.codepostal = V.codepostal
WHERE nom is null; -- faux
# region
1 nord
2 centre
3 corse
Le résultat est faux : Il y a 3 personnes qui habitent dans le nord. La requête doit donc se faire
en utilisant une sous requête qui détermine les codes de région où il n’y a personne
SELECT region
FROM regions R LEFT JOIN
(SELECT DISTINCT coderegion
FROM personnes P
JOIN villes V ON P.codepostal = V.codepostal) S
ON R.coderegion = S.coderegion
WHERE S.coderegion is null;
# region
1 centre
2 corse
- Afficher les nom des regions dans lesquelles n’intervient pas Alavie avec des jointures donc
sans utiliser IN comme au chapitre précédent
SELECT region
FROM regions
LEFT JOIN
(SELECT coderegion
FROM interventions I
JOIN personnes P ON I.codepersonne = P.codepersonne
WHERE nom = 'Alavie') sr1
ON regions.coderegion = sr1.coderegion
WHERE sr1.coderegion is null;
# region
1 sud
2 centre
3 corse
La jointure croisée CROSS JOIN ou simplement JOIN (sans ON) s’utilise lorsque’on cherche
des tuples (lignes) provenant de plusieurs tables qui n’apparaissent pas dans une autre. En
créant le produit relationnel associé à une jointure gauche on peut déterminer les lignes absentes
avec is null.
– pour chaque code de personne afficher les codes des regions dans lesquelles ils n’inter-
viennent pas
# codepersonne coderegion
1 2 2
2 2 3
3 2 4
4 3 1
5 3 3
6 3 4
7 4 1
8 4 3
9 4 4
On peut aussi écrire la requête avec l’opérateur EXCEPT
On peut aussi utiliser l’opérateur concat ( | | avec sqlite) même si ce n’est pas très ‘beau’ :
- pour chaque nom de personne afficher les noms des regions dans lesquelles ils n’interviennent
pas
# nom region
1 Alavie sud
2 Alavie centre
3 Alavie corse
4 Ancieux nord
5 Ancieux centre
6 Ancieux corse
7 Tete nord
8 Tete centre
9 Tete corse
Si on préfixe les champs d’une sous requête il faut les renommer.
CM5 : Regroupements
Les regroupements permettent de grouper des lignes et d’effectuer des sous totaux (fonctions
statistiques) sur ceux ci à la manière d’un sous total dans un tableur ou d’un tableau croisé,
une seule ligne étant affiché par groupe. Les champs affichés doivent être regroupés donc
on doit les trouver dans le GROUP BY. Les principales fonctions statistiques sont COUNT,
COUNT(DISTINCT x), SUM, AVG, MIN, MAX.
SELECT x, fonction(y)
FROM T
GROUP BY x
On veut calculer le nombre de villes par région. Commencons par afficher la table ville, les
groupes ont été ici séparés.
# coderegion ville
1 1 Lille
2 1 Lille
3 1 Roubaix
4 2 Montelimar
5 3 Paris
L’opération GROUP BY coderegion va créer les 3 groupes, il est impossible d’afficher les villes
car elles sont différentes au sein d’un même groupe
SELECT coderegion
FROM villes
32
Bases de Données MIASHS, Version 1.0
GROUP BY coderegion
ORDER BY coderegion;
# coderegion
1 1
2 2
3 3
Si vous ne voulez obtenir que ce résultat utilisez un DISTINCT et surtout pas un group by !
Si on veut calculer le nombre de villes il suffit de les compter au sein d’un même groupe
# coderegion nbvilles
1 1 3
2 2 1
3 3 1
Pourquoi compter les villes ? on peut compter les valeurs de n’importe quelle colonne à condi-
tion de ne pas avoir de null
# coderegion nbvilles
1 1 3
2 2 1
3 3 1
Si on veut ne compter qu’une seule fois Lille il faut effectuer un count(distinct)
# coderegion nbvilles
1 1 2
2 2 1
3 3 1
On commence par faire la requête sans GROUP BY avec les conditions dans le WHERE.
On groupe ensemble toutes les lignes qui sont identiques sur la ou les colonnes précisées dans
le GROUP BY.
Pour chacun de ces groupes de lignes, on produit une seule ligne, qui contient ces valeurs
identiques pour les colonnes du GROUP BY, et le résultat des opérations statistiques pour les
autres.
- Pour chaque departement, calculer le nombre de personnes
# dpt nb
1 26 1
2 59 3
On peut filtrer le résultat de deux façons : filtrer la ou les tables sur lesquelles on effectue les
opérations ou filtrer les lignes résultantes des groupements.
Si on veut filtrer les tables avant de grouper on veut alors filtrer suivant les champs ou les
opérations calculées sur une seule ligne, par exemple substr pour calculer le departement ou
quantité * prix. On utilisera un WHERE comme pour toutes les requêtes vues précédemment.
Si par contre on veut filtrer après le groupement, donc sur le résultat d’une opération statistique
comme count, il est clair que le filtre doit s’effectuer après le GROUP BY et pas avant au niveau
du WHERE. La clause HAVING placée après le GROUP BY permet d’écrire les conditions du
filtre.
– Afficher par code de personne le nombre de régions d’interventions dans les régions de code
1 ou 2. Le filtre porte ici sur les regions donc il s’ecrit dans le WHERE
# codepersonne nb
1 1 2
2 2 1
3 3 1
4 4 1
– Afficher par code de personne le nombre de régions d’interventions dans les régions de code
1 ou 2 pour les personnes qui interviennent dans au moins 2 régions. Le dernier filtre porte
ici sur le count donc il s’ecrit dans le HAVING
# codepersonne nb
1 1 2
On commence par faire la requête sans GROUP BY avec les conditions dans le WHERE.
On groupe ensemble toutes les lignes qui sont identiques sur la ou les colonnes précisées dans
le GROUP BY.
Pour chacun de ces groupes de lignes, on produit une seule ligne, qui contient ces valeurs
identiques pour les colonnes du GROUP BY, et le résultat des opérations statistiques pour les
autres.
On applique les filtres présents dans le HAVING sur les résultats obtenus par chacun des
groupes
- Afficher les departements avec au moins 2 personnes
# dpt
1 59
- Afficher les departements avec au moins 2 personnes ainsi que le nombre de personnes
# dpt nb
1 59 3
- Afficher les departements avec au moins 2 personnes qui gagnent au moins 20000C
# dpt
1 59
On peut bien sur utiliser des jointures comme pour toutes les requêtes
- Pour chaque région (son nom) où interviennent au moins deux personnes affichez le nombre
d’intervenants dans l’ordre décroissant du nombre d’intervenants.
# region nb
1 sud 3
2 nord 2
Les autojointures peuvent poser problème :
- pour chaque personne afficher le nombre de personnes qui gagne plus qu’elle. Attention,
toutes les personnes (4) doivent être affichées.
# nom nb
1 Alavie 2
2 Amelmou 1
3 Ancieux 3
4 Tete 0
On peut regrouper à plusieurs niveaux, dans ce cas les regroupements se font suivant l’ordre
des champs dans le GROUP BY.
- Afficher le nombre de personnes par region (d’habitation) et par tranche de salaire.
# region tranche nb
1 nord A 2
2 nord B 1
3 sud C 1
Il n’y a pas qu’une seule façon d’écrire une requête, en général le moteur SQL optimise.
Afficher la ville où il y a le plus grand nombre de personnes
- avec 2 sous requêtes dans le FROM : une qui calcule le nombre de personnes par ville (nbpers)
et une qui calcule le nombre de la ville la plus peuplée (nbmax)
SELECT ville
FROM villes,
(SELECT codepostal, count(*) AS nb
FROM personnes
GROUP BY codepostal) sr1,
(SELECT max(nb) AS maxPers
FROM (SELECT count(*) AS nb
FROM personnes
GROUP BY codepostal)
)
WHERE nb = maxPers
AND sr1.codepostal = villes.codepostal;
# ville
1 Lille
- avec une sous requête dans le FROM (nbpers) et une autre dans le WHERE (nbmax) :
SELECT ville
FROM villes,
(SELECT codepostal, count(*) AS nb
FROM personnes
GROUP BY codepostal) sr1
WHERE nb =
(SELECT max(nb) AS maxPers
FROM (SELECT count(*) AS nb
FROM personnes
GROUP BY codepostal)
)
AND sr1.codepostal = villes.codepostal;
# ville
1 Lille
- avec un HAVING (=nbmax)
SELECT ville
FROM personnes, villes
WHERE personnes.codepostal = villes.codepostal
GROUP BY villes.codepostal
HAVING count(*) =
(SELECT max(nb) AS maxPers
FROM (SELECT count(*) AS nb
FROM personnes
GROUP BY codepostal)
);
# ville
1 Lille
Opération de division : On veut obtenir les lignes d’une table T1 pour lesquelles les valeurs
d’une colonnes possèdent toutes les valeurs d’une colonne d’une autre table T2
- Afficher le nom des personnes qui interviennent ds tt les regions
SELECT nom
FROM personnes P JOIN interventions I ON P.codepersonne = I.
˓→codepersonne
GROUP BY nom
HAVING count(DISTINCT coderegion) = (SELECT count(*) FROM regions);
# nom
1 Amelmou
Lorsqu’on effectue une jointure interne entre 2 tables on obtient les lignes pour lesquelles une
association est possible. En regroupant suivant un champ on obtient donc au minimum une
ligne, la valeur minimale d’un count sera 1. La jointure externe permet d’obtenir les lignes
d’une table pour lesquelles il n’y a pas d’association, la valeur minimale d’un count porra donc
etre égale à 0.
– Afficher le nombre de personnes par villes
CM6 : Exercices
Les fonctions statistiques count, sum etc ... fonctionnent de la même façon qu’avec un tableur :
les valeur null sont ignorées (dans le cas d’un tableur sum(1,2,’a’) donne 3) :
# sum(B)
1 null
Par contre effectuer une opération avec null donne null :
# A+B
1 null
Les opérateurs logiques produisent null également :
# A
# A
1 3
39
Bases de Données MIASHS, Version 1.0
Le IN vérifie que les valeurs appartiennent à un ensemble, on vérifie que chaque valeur (donc
éventuellement plusieurs fois la même) appartient à l’ensemble
# X
1 1
2 2
3 3
4 3
Vérifier que X se trouve dans (1,2,3,3) est équivalent à vérifier qu’il se trouve dans (1,2,3) c’est
donc identique à vérifier qu’il se trouve dans les valeurs distinctes de (1,2,3,3), ce qui induit
qu’il est inutile de mettre un distinct dans la sous requête
# X
1 1
2 2
3 3
4 3
Si on veut afficher les valeurs distinctes (donc une seule fois la valeur 3) on écrit :
# X
1 1
2 2
3 3
6.2 La base
6.2. La base 40
Bases de Données MIASHS, Version 1.0
# A B
1 1 2
2 2 4
3 3 null
6.3 Questions
r2 :
r3 :
SELECT A * B FROM U;
r4 :
r5 :
r6 :
r7 :
r8 :
r9 :
r10 :
r11 :
6.3. Questions 41
Bases de Données MIASHS, Version 1.0
r12 :
r13 :
r14 :
r15 :
r16 :
r17 :
SELECT X FROM T T1
WHERE (SELECT SUM(Y) FROM T
WHERE T1.X = X) > (SELECT B FROM U WHERE A = X);
r18 :
r19 :
r20 :
r21 :
r22 :
6.3. Questions 42
Bases de Données MIASHS, Version 1.0
r23 :
r24 :
r25 :
ON T.Y = SR.B;
r26 :
SELECT B FROM U
WHERE A IN
(SELECT X FROM T GROUP BY X
HAVING SUM(Y) = (SELECT MAX(S) FROM
(SELECT SUM(Y) AS S FROM T GROUP
˓→BY X)));
r27 :
SELECT B FROM U,
(SELECT X, AVG(Y) AS nb FROM T GROUP BY X) SR1,
(SELECT MAX(nb) AS maxNb FROM (SELECT AVG(Y) AS nb FROM
˓→T GROUP BY X)) SR2
6.3. Questions 43
CHAPITRE 7
Requêtes simples
r1 : Affichez les noms des clients dans l’ordre alphabétique des noms
# nom
1 Aboucepartou
2 Adessin
3 Adlaplace
. .
586 Zieubleux
r2 : Affichez les noms et prénoms des clients dont le nom commence par Ta.
# nom prenom
1 Talonion Thomas
2 Tabille Raoul
3 Tabaniol Alphonse
. . .
13 Taijouhai Betty Barbara Noël Kathy Tess Sandra Lucille Ella
Parmillier Vick
r3 : Recherchez les clients dont le nom commence par Ta et dont le code postal est 59100
# nom prenom
1 Tamune Tablette D’Heuchokola Jean
r4 : Recherchez les clients dont le nom commence par Ta et qui habitent le Nord
# nom prenom
1 Taitraijeune Thérèse
2 Tamair Annick
3 Tamune Tablette D’Heuchokola Jean
4 Tafraise Théramène
r5 : Recherchez les clients dont le nom commence par Ta et qui habitent le Nord ou le Pas
de Calais
44
Bases de Données MIASHS, Version 1.0
# nom prenom
1 Taitraijeune Thérèse
2 Tart’inn Kimberley
3 Tamair Annick
. . .
6 Taijouhai Betty Barbara Noël Kathy Tess Sandra Lucille Ella
Parmillier Vick
r6 : Recherchez les clients dont le nom commence par Ta et qui n’habitent ni le Nord ni
le Pas de Calais
# nom prenom
1 Talonion Thomas
2 Tabille Raoul
3 Tabaniol Alphonse
. . .
7 Tabaton Jean
r7 : Affichez les numéros de tous les produits dans l’ordre des numproduit
# numproduit
1 2
2 3
3 4
. .
31 32
r8 : Affichez les numéros des produits qui ont été commandés
# refproduit
1 2
2 3
3 4
. .
31 32
r9 : Affichez les numéros de marques et les noms des produits de la categorie 3 dans
l’ordre decroissant des numéros de marques et l’ordre alphabétique des noms
# refmarque nom
1 17 Super guide tradition
2 16 Vetta
3 15 Alpinist
. . .
6 5 Super Khumbu
r10 : Affichez les nom des produits de la categorie 1 dans l’ordre croissant de la longueur
des noms
# nom
1 Clean
2 Manga
3 Miura
. .
6 Diamond lady
45
Bases de Données MIASHS, Version 1.0
46
Bases de Données MIASHS, Version 1.0
# nb
1 353
r19 : Calculer le nombre de marques
# nb
1 26
r20 : Calculer le nombre de marques associées à des produits
# nb
1 23
Case When.
r21 : Les produits de la marque 3 subissent une hausse de 5%, ceux de la marque 4 une
hausse de 10%, afficher les nouveaux prix des produits
# nom nouveauPrix
1 Ninja baby 235
2 Monkey 254
3 Clean 210.0
. . .
31 Cremes et gel indice 25 99
47
CHAPITRE 8
48
Bases de Données MIASHS, Version 1.0
# nom
1 Diamond lady
2 Manga
3 Miura
. .
13 Nepal top
r7 : Affichez la date des commandes effectuées par le client Alavie
# date
1 1997/01/22
2 1997/02/02
r8 : Affichez la date de la première commande effectuée par le client Tabille
# minDate
1 1996/12/22
r9 : Affichez le nombre d’articles achetés par le client de code 5 le jour de sa dernière
commande
# nbArticles
1 5
r10 : Affichez les nom et prénom des clients qui ont effectué des commandes entre le jour
de la première commande d’Alavie et le jour de sa dernière commande
# nom
1 Aulet
2 Talonion
3 Leupoisson
. .
8 Seiglandieu
r11 : Affichez le nom des produits de la même marque que le produit Miura
# nom
1 K2 Rosso
2 Nepal top
r12 : Affichez dans l’ordre alphabétique le nom et prénom des clients qui ont acheté au
moins un des produits acheté par Alavie
# nom prenom
1 Aboucepartou Thècle
2 Adlaplace Andreï
3 Al Poubayl Ahmed
. . .
42 Yala Couvertur Kigratt Sandra
r13 : Affichez les nom et prénom des clients qui habitent la même ville que Peuleurido
# nom prenom
1 Deulisse Fleur
2 Attan Charles
3 Sanfraper André
. . .
13 Yoraitoux Aline
49
Bases de Données MIASHS, Version 1.0
r14 : Affichez par ordre alphabétique inverse les noms des produits qui ont été vendus en
quantité >= 15
# nom
1 Tube-stick indice 8
2 Super Khumbu
3 K2 Rosso
. .
6 Alpinist
r15 : Affichez par ordre alphabétique les noms des produits qui ont été vendus en quantité
>= 15 et dont le prix unitaire est > 900 C
# nom
1 Aventure 65
2 K2 Rosso
r16 : Affichez le nom et prénom des clients qui ont acheté de produits de plus de 1000
euros
# nom prenom
1 Alavie Irenée
2 Duman Mariette
3 Deulisse Fleur
. . .
26 Savajamère André
50
CHAPITRE 9
TD4 : Jointures
r1 : Pour chaque produit, afficher sa marque et son nom dans l’ordre des marques puis
des produits
# nom nom
1 Boreal Ninja baby
2 Climbing shoes Clean
3 EB Monkey
. . .
31 vertical Grimpeur
r2 : Même question mais limitée aux produits de la catégorie Protection solaire
# nom nom
1 piz buin Cremes et gel indice 25
2 piz buin Cremes et gel indice 4
3 uv control Tube-stick indice 15
. . .
6 uv control Tube-stick indice 8
r3 : Affichez les noms des personnes de Lille en utilisant une jointure
# nom
1 Deulisse
2 Peuleurido
3 Attan
. .
14 Yoraitoux
r4 : Affichez les noms des produits qui ont été achetés en quantité > 2 pour au moins une
commande
# nom
1 Diamond lady
2 Monkey
3 Super Khumbu
. .
21 Palette
r5 : Afficher la quantité et le prix des produits de la commande 1
51
Bases de Données MIASHS, Version 1.0
# quantite prix
1 3 550
2 1 949
3 1 1312
4 1 144
r6 : Pour chaque produit commandé dans la commande 1 affichez son nom et le prix à
payer en fonction de la quantité
# nom totalLigne
1 Diamond lady 1650
2 Aventure 65 949
3 Super guide tradition 1312
4 Charlotte 144
r7 : Afficher le montant de la commande 1
# totalCommande
1 4055
r8 : Affichez les noms et prénoms des clients qui habitent la même ville que Peuleurido
avec une autojointure
# nom prenom
1 Attan Charles
2 Baymole Rémi
3 Deuf John
. . .
13 Zettofrais Mélanie
r9 : Affichez dans l’ordre alphabétique le nom et prénom des clients qui ont acheté au
moins un des produits acheté par Alavie avec une jointure
# nom prenom
1 Aboucepartou Thècle
2 Adlaplace Andreï
3 Al Poubayl Ahmed
. . .
42 Yala Couvertur Kigratt Sandra
r10 : Nom du client qui a acheté le produit le plus cher en janvier (de n’importe quelle
annee)
# nom prenom
1 Citation Félix
r11 : Quels sont les clients qui ont acheté le produit le plus cher acheté par Pige
# clients.nom
1 Dumonde
2 Yala Couvertur Kigratt
3 Adrouille Toultan
r12 : Une réduction de 10% est accordée pour chaque produit commandé en quantité
supérieure ou égale à 3. Pour chaque produit commandé dans la commande 1 affichez
le nom du produit, le total sans réduction, le montant de la réduction et le montant avec
réduction
52
Bases de Données MIASHS, Version 1.0
53
CHAPITRE 10
TD5 : Regroupements
54
Bases de Données MIASHS, Version 1.0
r6 : Affichez le nom et le prénom des clients qui ont acheté des produits de plus de 3
marques différentes
# nom prenom
1 Al Poubayl Ahmed
2 Alavie Irenée
3 Baul Gérald
. . .
11 Touténe Hervé
r7 : Affichez le nombre de produits différents commandés par le client Alavie par com-
mande
# numcommande nbProduits
1 1 4
2 14 4
r8 : Affichez le nombre d’articles commandés par le client Alavie par commande
# numcommande nbArticles
1 1 6
2 14 6
r9 : Affichez le montant et la date des commandes effectuées par le client Tabille
# date montant
1 1996/12/22 126
2 1996/12/22 3111
3 1997/02/22 1955
r10 : Affichez le nom et prénom des clients dont le total des commandes est de plus de
5000 C
# nom prenom
1 Alavie Irenée
2 Daicacahuett’Livair Yvan
3 Juskalapporte Hercule
. . .
6 Yala Couvertur Kigratt Sandra
r11 : Affichez le nom et prénom des clients qui ont effectué au moins une commande de
plus de 5000 C
# nom prenom
1 Daicacahuett’Livair Yvan
2 Juskalapporte Hercule
3 Yala Couvertur Kigratt Sandra
r12 : Affichez le montant de la plus grande commande
# maxMontant
1 6515
r13 : Affichez les noms et prénoms des clients qui ont achetés plus que Tabille (au total)
# nom prenom
1 Alavie Irenée
2 Daicacahuett’Livair Yvan
3 Juskalapporte Hercule
. . .
5 Yala Couvertur Kigratt Sandra
55
Bases de Données MIASHS, Version 1.0
r14 : Affichez le nom et prénom du client qui a effectué la plus grande commande
# nom prenom
1 Juskalapporte Hercule
r15 : Affichez le total des montants des commandes par an
# annee montant
1 1995 9009
2 1996 96147
3 1997 61085
r16 : Affichez l’année pour laquelle le total des montants des commandes est le plus faible
# annee
1 1995
r17 : Affichez le montant des plus grandes commandes par client dans l’ordre decroissant
des montants
# nom maxMontant
1 Juskalapporte 6515
2 Daicacahuett’Livair 5835
3 Yala Couvertur Kigratt 5225
. . .
109 Plupersonne 49
r18 : Affichez les noms des clients qui ont effectués en août 1996 une commande de mon-
tant supérieur à celle qui a été la plus grande en janvier 1996
# nom prenom
1 Juskalapporte Hercule
56
CHAPITRE 11
TD6 : Synthèse
r1 : Affichez le nom et prénom des clients qui ont effectué une commande supérieure à la
moyenne des commandes
# nom prenom
1 Alavie Irenée
2 O’Faringite Reine
3 Atrovite Yves
. . .
43 Tison Paco
r2 : Affichez le nom de la ville d’ou provient le plus grande nombre de commandes
# Ville
1 Quesnoy sur Deule
r3 : Affichez le nom des villes qui font moins que 5% du nombre de commande
# Ville nbCommandes
1 Arras 3
2 Auchel 5
3 Brest 1
. . .
36 Velizy 3
r4 : Afficher le nom de la marque préférée (celle qui apparait le plus dans les commandes)
dans l’ordre du nombre de commandes
# nom
1 uv control
r5 : Par catégorie, afficher le nom de la marque préférée
# nom nom
1 Chaussons d_escalade Boreal
2 Vetements de grimpe stone monkey
3 Chaussures d_alpinisme La sportiva
. . .
6 Sac a dos Millet
r6 : Affichez le classement des produits suivant les quantités demandées dans l’ordre
decroissant, les produits invendus devront apparaitre
57
Bases de Données MIASHS, Version 1.0
# total nom
1 23 Aventure 65
2 21 K2 Rosso
3 18 Tube-stick indice 8
. . .
31 5 Tube-stick indice 15
r7 : Affichez le nom des clients réguliers : ceux qui font un nombre de commandes autour
de 30% de la moyenne du nombre de commandes des clients.
# nom
1 Talonion
2 Duman
3 Leupoisson
. .
99 Savajamère
r8 : Affichez le nom des clients de panier réguliers : ceux qui font des commandes autour
de 30% de la moyenne des commandes des clients.
# nom
1 Tabille
2 Use
3 O’Faringite
. .
23 Savajamère
r9 : Affichez les noms des client de profil type : les clients réguliers et de panier réguliers
# nom
1 Use
2 Deulisse
3 Duveldyv
. .
19 Savajamère
r10 : Affichez les noms des clients et le panier moyen des clients de profil type
# nom moyPanier
1 Use 1172.0
2 Deulisse 1099.0
3 Duveldyv 1079.0
. . .
19 Savajamère 1719.0
r11 : Les requêtes devenant assez pénible à écrire, creez une vue qui affiche les références
des client de profil type. On utilisera ensuite cette vue pour les autres questions.
# CreateView
1 OK
r12 : Affichez les noms des client de profil type en utisant la vue
58
Bases de Données MIASHS, Version 1.0
# nom
1 Use
2 Deulisse
3 Duveldyv
. .
19 Savajamère
r13 : Affichez par an le montant total des paniers des clients de profil type
# annee montantTotal
1 1995 2102
2 1996 16030
3 1997 5985
r14 : Affichez par an le montant de l’évolution des paniers de profil type par rapport à
l’année précédente.
# annee evolution
1 1996 13928
2 1997 -10045
r15 : Affichez par an la difference entre le montant attendu des paniers de profil type et
le montant réalisé
# annee difference
1 1995 6907
2 1996 80117
3 1997 55100
r16 : Affichez par an l’évolution de ce differentiel. La requete précédente sera donc utilisée
2 fois.
# sr1.annee evolution
1 1995 73210
2 1996 -25017
59
CHAPITRE 12
Cinema1
12.1 La base
12.2 Questions
60
Bases de Données MIASHS, Version 1.0
r3 : Titres des films avec leur réalisateur, dans l’ordre alphabétique des titres de film
# titre realisateur
1 Annee du soleil calme Krzysztof
2 Appocalypse now Coppola
3 Baxter Boivin
. . .
33 Veuve mais pas trop Truffaut
r4 : Nom des réalisateurs qui commencent par un T
# realisateur
1 Truffaut
r5 : Noms et numéros des acteurs du film “Cop”
# nomacteur
1 Eastwood
2 Woods
3 Deneuve
. .
5 Haid
r6 : Années de sortie des films tournés avec Gabin dans l’ordre des dates
# annee
1 1962
2 1989
r7 : Films à l’affiche de la quatrième semaine dans chaque salle du cinéma gaumont
# salle titre
1 1 Mon cher sujet
2 2 Annee du soleil calme
3 3 Un poisson nomme wanda
. . .
6 6 La boca del lobo
r8 : Acteurs qui ont tourné avec Truffaut comme réalisateur
# idacteur nomacteur
1 23 Pfeiffer
2 19 Modine
3 29 Stockwell
. . .
5 24 Piccoli
r9 : Adresses des cinémas où passe un film réalisé par Crichton
12.2. Questions 61
Bases de Données MIASHS, Version 1.0
# nomcine rue
1 gaumont alsace lorraine
2 la nef edouard rey
3 ugc royal clot bey
. . .
5 les 6 rex saint jacques
r10 : Rues, salles et nombres de places des cinémas où sont joués des films sortis en 1984
et dans lesquels joue Delon
# rue salle nbplaces
1 alsace lorraine 5 100
2 saint jacques 1 400
3 strasbourg 1 200
4 grenette 6 100
r11 : Titres et semaines de programmation des films dans lesquels jouent Deneuve ou
Eastwood
# titre semaine
1 Cop 1
2 Cop 2
3 Cop 3
. . .
8 La derniere cible 4
r12 : Pour chaque réalisateur, nom des acteurs qui ont tourné sous sa direction en 1989,
trié par ordre alphabétique de nom de réalisateur puis par ordre alphabétique inverse de
nom d’acteur.
# realisateur nomacteur
1 Boivin Spiesser
2 Boivin Piccoli
3 Boivin Mercure
. . .
30 Truffaut Modine
12.2. Questions 62
CHAPITRE 13
Cinema2
13.1 Questions
63
Bases de Données MIASHS, Version 1.0
# titre nbSemaines
1 Annee du soleil calme 4
2 Baxter 4
3 Cop 4
. . .
9 Veuve mais pas trop 5
r6 : Titre des films qui passaient la semaine 4, avec le nombre de cinémas dans lesquels
ils étaient programmés, limités à ceux programmés dans au moins 4 cinémas, triés dans
l’ordre du nombre de cinémas dans lesquels ils étaient programmés.
# titre nbCinemas
1 Annee du soleil calme 5
2 La baie des anges 5
3 Un poisson nomme wanda 5
. . .
8 Mon cher sujet 4
r7 : Avec une sous-requête, afficher les films qui ont été tournés la même année que Nikita”
# titre
1 Annee du soleil calme
2 Cop
3 La boca del lobo
. .
8 Cyrano de Bergerac
r8 : Box office (=les films dans l’ordre décroissant du nombre d’entrées) de la semaine 4
(titre, réalisateur, nombre d’entrées).
# titre realisateur nbTotalEntrees
1 Un poisson nomme wanda Crichton 3013
2 Annee du soleil calme Krzysztof 2679
3 Veuve mais pas trop Truffaut 2364
. . . .
9 Baxter Boivin 101
r9 : Avec une auto jointure, afficher les films qui ont été tournés la même année que Nikita
# titre
1 Annee du soleil calme
2 Baxter
3 Cop
. .
8 Veuve mais pas trop
r10 : Avec une aujointure Acteurs partenaires de Deneuve
# nomacteur
1 Eastwood
2 Haid
3 Warren
. .
7 Hunt
r11 : Réalisateurs ayant joué dans des films qu’ils n’ont pas réalisés eux-même
13.1. Questions 64
Bases de Données MIASHS, Version 1.0
# nomacteur
1 Eastwood
2 Truffaut
r12 : Réalisateurs et noms des films précédés dans la programmation par un film dans
lequel joue Pfeiffer
# nomacteur nbPartenaires
1 Delon 9
2 Piccoli 9
3 Deneuve 7
. . .
34 Vega 1
r13 : Avec une sous requete Acteurs partenaires de Deneuve
# nomacteur
1 Eastwood
2 Woods
3 Warren
. .
7 Delon
r14 : Liste des acteurs avec le nombre de leurs partenaires (c’est à dire le nombre des
acteurs avec lesquels ils ont joué dans au moins un film), dans l’ordre décroissant du
nombre de partenaires.
# nomacteur partenaires
1 Delon 9
2 Piccoli 9
3 Deneuve 7
. . .
34 Vega 1
r15 : Titre, année et pays des films pour lesquels il existe un film réalisé la même année
dans le même pays.
# titre annee pays
1 La derniere cible 1984 USA
2 Birdy 1984 USA
3 Mon cher sujet 1989 France
. . . .
15 JFK 1991 USA
r16 : Analyse de la concurrence : pour chaque paire de cinémas (C1, C2), nombre de films
identiques programmés simultanément. La liste doit être triée par C1 puis par nombre de
films simultanés (dans l’ordre décroissant), puis par C2.
# nomcine Communs nomcine
1 gaumont 7 gaumont
2 gaumont 5 la nef
3 gaumont 5 le club
. . . .
64 ugc royal 2 les dauphins
r17 : Noms des cinémas ayant programmé un même film dans des salles différentes.
13.1. Questions 65
Bases de Données MIASHS, Version 1.0
# idcine nomcine
1 1 le club
2 7 ugc royal
r18 : Pour chaque pays, donnez le nombre moyen d’acteurs par film.
# pays x
1 Espagne 2
2 Pologne 4
3 USA 4
4 France 5
r19 : Pour chaque année, noms des cinémas ayant eu à l’affiche tous les films sortis cette
année.
# annee nomcine
1 1962 le club
2 1962 les dauphins
3 1962 les 6 rex
. . .
5 1962 pathe grenette
13.1. Questions 66
CHAPITRE 14
Cinema3
14.1 Questions
67
Bases de Données MIASHS, Version 1.0
# titre
1 Nikita
2 L’amant
3 La belle histoire
. .
24 Les visiteurs
r6 : cinema qui n’ont rien programme la semaine 4
# nomcine
1 lux
2 vox
r7 : film qui a fait le plus grand nombre d’entrees
# titre
1 Un poisson nomme wanda
r8 : films dont le nombre d’entrees est superieur a la moyenne des entrees par semaine
# titre
1 Annee du soleil calme
2 Cop
3 Un poisson nomme wanda
. .
7 Veuve mais pas trop
r9 : films dont le nombre d’entrées est égal à +/- 5 % de la moyenne des entrées par
semaine
# titre
1 Cop
2 Un poisson nomme wanda
3 Mon cher sujet
4 Veuve mais pas trop
r10 : les realisateurs sont payes 100000 euros avec une subvention de 50000 euros s’ils
réalisent un film en France, calculer le salaire total des realisateurs
# realisateur salaire
1 Annaud 150000
2 Besson 300000
3 Blier 150000
. . .
27 Truffaut 250000
r11 : nombre de films par mois et par cinema, on notera Jamais si un cinema ne pro-
gramme aucun film
# nomcine mois nbFilms
1 gaumont Janvier 7
2 la nef Janvier 6
3 le club Janvier 7
. . . .
12 vox Jamais 0
r12 : realisateur qui a fait le + grand nombre de films
14.1. Questions 68
Bases de Données MIASHS, Version 1.0
# realisateur
1 Parker
r13 : acteur le plus rentable (+ grand nombre d’entrées)
# nomacteur
1 Piccoli
r14 : realisateurs qui ne sont pas acteurs ss jointure gauche
# realisateur
1 Krzysztof
2 Harris
3 Lombardi
. .
25
3. Clavier
r16 : par cinema liste des films qui ont un nb d’entrées inférieur à la moitié du nb de place
tt salles confondues la semaine 4
# nomcine titre
1 le club La baie des anges
2 les dauphins Annee du soleil calme
3 les dauphins La baie des anges
. . .
11 le melies Veuve mais pas trop
r17 : nb de films par première lettre (A :2) : substr(champ,debut,nb)
# initiale nb
1 A 2
2 B 2
3 C 2
. . .
17 V 1
r18 : realisateur qui a tourné avec le plus grand nombre d’acteurs
# realisateur
1 Boivin
r19 : les acteurs ont un intéressement de 0.5 euro par entrée d’un film si le nombre d’en-
trées de ce film dépasse 10000, pour chaque acteur ayant obtenu des intéressements affi-
cher leur montant total
14.1. Questions 69
Bases de Données MIASHS, Version 1.0
# nomacteur interessement
1 Cleese 8952.5
2 Curtis 8952.5
3 Gabin 5452.0
. . .
8 Wilson 5452.0
r20 : le tarif des entrées des cinémas est de 6 C sauf ‘le melies’ : 5 C et ‘le club’ : 3 C. Quelle
est la recette totale des cinemas
# nomcine recette
1 gaumont 138160
2 la nef 152032
3 le club 17202
. . .
8 ugc royal 53848
r21 : pour ‘le club’, par salle et par film, afficher ‘abandonner’ si le taux d’occupation de
la semaine 4 est inférieur à 20% des places de la salle, ‘ouvrir’ s’il est supérieur à 80%
sinon ‘continuer’
# salle titre action
1 1 Veuve mais pas trop abandonner
2 2 La boca del lobo abandonner
3 3 La baie des anges ouvrir
. . . .
5 5 Cop continuer
r22 : par cinema et par semaine, liste des salles sans programmation
# nomcine salle
1 lux 1
2 les 6 rex 6
r23 : acteurs qui n’ont pas tourné de films au USA mais qui en ont tourné en Espagne
# nomacteur
1 Bueno
2 Vega
14.1. Questions 70
CHAPITRE 15
r1 :
== === ====
# X Y
== === ====
1 3 2
2 3 1
== === ====
r2 :
== =====
# A
== =====
1 3
2 1
3 2
== =====
r3 :
SELECT A * B FROM U;
== ========
# A * B
== ========
1 2
2 8
3
== ========
71
Bases de Données MIASHS, Version 1.0
r4 :
== =====
# Y
== =====
1 1
2 2
3 4
== =====
r5 :
== === ====
# X A
== === ====
1 1 2
2 2 1
3 3 1
4 3
== === ====
r6 :
== ========
# A - X
== ========
1 -1
== ========
r7 :
== =========
# SUM(A)
== =========
1 6
== =========
r8 :
72
Bases de Données MIASHS, Version 1.0
== ===========
# COUNT(Y)
== ===========
1 1
2 2
== ===========
r9 :
== =========
# SUM(B)
== =========
1 24
== =========
r10 :
== =========
# SUM(B)
== =========
1 8
2 16
3
== =========
r11 :
== =========
# SUM(Y)
== =========
1 1
2 4
3 4
== =========
r12 :
73
Bases de Données MIASHS, Version 1.0
== =============
# SUM(X * B)
== =============
1
2 18
3 36
== =============
r13 :
== =====
# X
== =====
1 1
2 2
3 3
4 3
== =====
r14 :
== =====
# X
== =====
1 1
2 2
== =====
r15 :
== =====
# X
== =====
1 1
2 2
== =====
r16 :
74
Bases de Données MIASHS, Version 1.0
== =====
# A
== =====
1 3
== =====
r17 :
SELECT X FROM T T1
WHERE (SELECT SUM(Y) FROM T
WHERE T1.X = X) > (SELECT B FROM U WHERE A = X);
== =====
# X
== =====
1 1
== =====
r18 :
== =====
# X
== =====
1 1
2 3
3 3
== =====
r19 :
== =====
# A
== =====
1 1
== =====
r20 :
75
Bases de Données MIASHS, Version 1.0
== =====
# A
== =====
1 1
2 2
== =====
r21 :
== =====
# A
== =====
1 2
== =====
r22 :
== ===========
# MIN(T.Y)
== ===========
1 2
== ===========
r23 :
== === =============
# X COUNT(T1.X)
== === =============
1 2 1
2 3 4
== === =============
r24 :
76
Bases de Données MIASHS, Version 1.0
== === ==========
# X COUNT(B)
== === ==========
1 1 1
2 2 1
3 3 0
== === ==========
r25 :
ON T.Y = SR.B;
== ========
# (T.Y)
== ========
1 4
2 2
== ========
r26 :
SELECT B FROM U
WHERE A IN
(SELECT X FROM T GROUP BY X
HAVING SUM(Y) = (SELECT MAX(S) FROM
(SELECT SUM(Y) AS S FROM T GROUP
˓→BY X)));
== =====
# B
== =====
1 2
== =====
r27 :
SELECT B FROM U,
(SELECT X, AVG(Y) AS nb FROM T GROUP BY X) SR1,
(SELECT MAX(nb) AS maxNb FROM (SELECT AVG(Y) AS nb FROM
˓→T GROUP BY X)) SR2
== =====
# B
== =====
77
Bases de Données MIASHS, Version 1.0
1 2
== =====
78
CHAPITRE 16
r1 : Affichez les noms des clients dans l’ordre alphabétique des noms
select nom
from clients
order by nom;
r2 : Affichez les noms et prénoms des clients dont le nom commence par Ta.
r3 : Recherchez les clients dont le nom commence par Ta et dont le code postal est 59100
r4 : Recherchez les clients dont le nom commence par Ta et qui habitent le Nord
r5 : Recherchez les clients dont le nom commence par Ta et qui habitent le Nord ou le Pas
de Calais
r6 : Recherchez les clients dont le nom commence par Ta et qui n’habitent ni le Nord ni
le Pas de Calais
79
Bases de Données MIASHS, Version 1.0
r7 : Affichez les numéros de tous les produits dans l’ordre des numproduit
select numproduit
from produits
order by numproduit;
r9 : Affichez les numéros de marques et les noms des produits de la categorie 3 dans
l’ordre decroissant des numéros de marques et l’ordre alphabétique des noms
r10 : Affichez les nom des produits de la categorie 1 dans l’ordre croissant de la longueur
des noms
select nom
from produits
where refcateg = 1
order by length(nom);
r11 : Affichez les nom des produits de la categorie 1 de plus de 5 caractères dans l’ordre
croissant de la longueur des noms
select nom
from produits
where refcateg = 1
and length(nom) > 5
order by length(nom);
r12 : Afficher les noms et le prix HT des produits dans l’ordre croissant des prix HT (tva
de 20%)
r13 : Afficher les noms, le prix HT, le montant de la TVA et le prix TTC des produits dans
l’ordre des noms
80
Bases de Données MIASHS, Version 1.0
from produits
order by nom;
from produits;
select sum(quantite) as nb
from procom;
select count(*) as nb
from marques;
r21 : Les produits de la marque 3 subissent une hausse de 5%, ceux de la marque 4 une
hausse de 10%, afficher les nouveaux prix des produits
select nom,
case refmarque
when 3 then prix * 1.05
when 4 then prix * 1.1
else prix
end as nouveauPrix
from produits;
81
Bases de Données MIASHS, Version 1.0
select nom,
case
when refmarque = 3 then prix * 1.05
when refmarque = 4 then prix * 1.1
else prix
end as nouveauPrix
from produits;
82
CHAPITRE 17
select nom
from clients
where codepostal in
(select codepostal from villes
where ville = 'Lille');
select nom
from clients
where codepostal in
(select codepostal from villes
where ville = 'Lille' or ville = 'Roubaix');
select nom
from clients
where codepostal in
(select codepostal from villes
where ville IN ('Lille', 'Roubaix'));
r3 : Afficher les noms des clients dont le nom commence par Ta et qui ont effectué une
commande
select nom
from clients
where nom like 'Ta%'
and numclient in
(select refclient
from commandes);
83
Bases de Données MIASHS, Version 1.0
select nom
from clients
where numclient =
(select refclient
from commandes
where numcommande = 1);
r5 : Afficher les noms des clients qui ont effectué une commande en janvier 1997
r6 : Affichez les noms des produits de prix supérieur à la moyenne des prix
select nom
from produits
where prix >
(select avg(prix)
from produits);
select date
from commandes
where refclient =
(select numclient
from clients
where nom = 'Alavie');
84
Bases de Données MIASHS, Version 1.0
(select max(date)
from commandes
where refclient = 5)
and refclient = 5);
r10 : Affichez les nom et prénom des clients qui ont effectué des commandes entre le jour
de la première commande d’Alavie et le jour de sa dernière commande
-- avec between
85
Bases de Données MIASHS, Version 1.0
r11 : Affichez le nom des produits de la même marque que le produit Miura
select nom
from produits
where refmarque =
(select refmarque
from produits
where nom = 'Miura')
and nom != 'Miura';
r12 : Affichez dans l’ordre alphabétique le nom et prénom des clients qui ont acheté au
moins un des produits acheté par Alavie
r13 : Affichez les nom et prénom des clients qui habitent la même ville que Peuleurido
86
Bases de Données MIASHS, Version 1.0
r14 : Affichez par ordre alphabétique inverse les noms des produits qui ont été vendus en
quantité >= 15
select nom
from produits
where (
select sum(quantite)
from procom
where numproduit = refproduit) >= 15
order by nom desc;
r15 : Affichez par ordre alphabétique les noms des produits qui ont été vendus en quantité
>= 15 et dont le prix unitaire est > 900 C
select nom
from produits
where (
select sum(quantite)
from procom
where numproduit = refproduit) >= 15
and prix > 900
order by nom;
r16 : Affichez le nom et prénom des clients qui ont acheté de produits de plus de 1000
euros
87
CHAPITRE 18
r1 : Pour chaque produit, afficher sa marque et son nom dans l’ordre des marques puis
des produits
select nom
from clients join villes on clients.codepostal = villes.
˓→codepostal
r4 : Affichez les noms des produits qui ont été achetés en quantité > 2 pour au moins une
commande
r6 : Pour chaque produit commandé dans la commande 1 affichez son nom et le prix à
payer en fonction de la quantité
88
Bases de Données MIASHS, Version 1.0
r8 : Affichez les noms et prénoms des clients qui habitent la même ville que Peuleurido
avec une autojointure
r9 : Affichez dans l’ordre alphabétique le nom et prénom des clients qui ont acheté au
moins un des produits acheté par Alavie avec une jointure
r10 : Nom du client qui a acheté le produit le plus cher en janvier (de n’importe quelle
annee)
89
Bases de Données MIASHS, Version 1.0
r11 : Quels sont les clients qui ont acheté le produit le plus cher acheté par Pige
r12 : Une réduction de 10% est accordée pour chaque produit commandé en quantité
supérieure ou égale à 3. Pour chaque produit commandé dans la commande 1 affichez
le nom du produit, le total sans réduction, le montant de la réduction et le montant avec
90
Bases de Données MIASHS, Version 1.0
réduction
select sum(
quantite*prix * case when quantite >= 3 then 0.9
else 1 end) as montant
from procom join produits on numproduit = refproduit
where refcommande = 1;
r14 : Affichez par ordre alphabétique les noms des clients qui n’ont rien commandé
select nom
from clients left join commandes on numclient = refclient
where numcommande is null
order by nom;
r15 : Affichez le nom et prénom des clients qui n’ont pas acheté de produits de moins de
1000 euros avec ceux qui n’ont rien acheté
91
CHAPITRE 19
r6 : Affichez le nom et le prénom des clients qui ont acheté des produits de plus de 3
marques différentes
92
Bases de Données MIASHS, Version 1.0
r7 : Affichez le nombre de produits différents commandés par le client Alavie par com-
mande
r10 : Affichez le nom et prénom des clients dont le total des commandes est de plus de
5000 C
r11 : Affichez le nom et prénom des clients qui ont effectué au moins une commande de
plus de 5000 C
93
Bases de Données MIASHS, Version 1.0
r13 : Affichez les noms et prénoms des clients qui ont achetés plus que Tabille (au total)
-- Avec un having
r14 : Affichez le nom et prénom du client qui a effectué la plus grande commande
-- Avec un having
94
Bases de Données MIASHS, Version 1.0
r16 : Affichez l’année pour laquelle le total des montants des commandes est le plus faible
r17 : Affichez le montant des plus grandes commandes par client dans l’ordre decroissant
des montants
95
Bases de Données MIASHS, Version 1.0
r18 : Affichez les noms des clients qui ont effectués en août 1996 une commande de mon-
tant supérieur à celle qui a été la plus grande en janvier 1996
96
CHAPITRE 20
r1 : Affichez le nom et prénom des clients qui ont effectué une commande supérieure à la
moyenne des commandes
SELECT sr1.Ville
FROM
-- nombre de commandes par ville
(SELECT Ville,
Count(numcommande) AS nbCommandes
FROM Villes
JOIN clients ON Villes.CodePostal = clients.CodePostal
JOIN commandes ON numclient = refclient
GROUP BY Ville) sr1,
-- maximum de ces nombres de commandes
(SELECT Max(nbCommandes) AS maxNbCommandes
FROM (SELECT Count(numcommande) AS nbCommandes
FROM Villes
JOIN clients ON Villes.CodePostal = clients.
˓→CodePostal
97
Bases de Données MIASHS, Version 1.0
r3 : Affichez le nom des villes qui font moins que 5% du nombre de commande
r4 : Afficher le nom de la marque préférée (celle qui apparait le plus dans les commandes)
dans l’ordre du nombre de commandes
SELECT marques.nom
FROM marques,
(SELECT refmarque,
Count(refmarque) AS nbMarques
FROM produits
JOIN procom ON numproduit = refproduit
GROUP BY refmarque) sr1,
FROM produits
JOIN procom ON numproduit = refproduit
GROUP BY refcateg, refmarque) sr1,
98
Bases de Données MIASHS, Version 1.0
r6 : Affichez le classement des produits suivant les quantités demandées dans l’ordre
decroissant, les produits invendus devront apparaitre
r7 : Affichez le nom des clients réguliers : ceux qui font un nombre de commandes autour
de 30% de la moyenne du nombre de commandes des clients.
SELECT nom
FROM clients,
(SELECT refclient, Count(numcommande) AS nbCommandes --8a
FROM commandes
GROUP BY refclient) sr1,
r8 : Affichez le nom des clients de panier réguliers : ceux qui font des commandes autour
de 30% de la moyenne des commandes des clients.
SELECT nom
FROM clients,
(SELECT sr1.refclient as refclient --9d
FROM (SELECT refclient, Avg(montant) AS moyMontant --9c
FROM (SELECT refclient, numcommande, Sum(quantite
˓→* Prix) AS montant --9a montant commandes clients
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
99
Bases de Données MIASHS, Version 1.0
r9 : Affichez les noms des client de profil type : les clients réguliers et de panier réguliers
SELECT nom
FROM clients,
----------------
(SELECT sr1.refclient as refclient
FROM (SELECT sr1.refclient as refclient
FROM (SELECT refclient, Avg(montant) AS moyMontant
FROM (SELECT refclient, numcommande,
˓→Sum(quantite * Prix) AS montant
FROM produits
JOIN commandes ON numproduit =
˓→refproduit
FROM commandes
GROUP BY refclient) sr1,
100
Bases de Données MIASHS, Version 1.0
r10 : Affichez les noms des clients et le panier moyen des clients de profil type
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY refclient, numcommande)
GROUP BY refclient) sr1,
FROM commandes
GROUP BY refclient) sr1,
101
Bases de Données MIASHS, Version 1.0
r11 : Les requêtes devenant assez pénible à écrire, creez une vue qui affiche les références
des client de profil type. On utilisera ensuite cette vue pour les autres questions.
FROM produits
JOIN commandes ON numproduit =
˓→refproduit
FROM commandes
GROUP BY refclient) sr1,
r12 : Affichez les noms des client de profil type en utisant la vue
102
Bases de Données MIASHS, Version 1.0
SELECT nom
FROM clients, clientstype
WHERE numclient = refclient;
r13 : Affichez par an le montant total des paniers des clients de profil type
FROM commandes,
(SELECT refclient, numcommande, Sum(quantite * Prix) AS
˓→montant --9a montant commandes clients
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY refclient, numcommande) sr1,
clientstype
WHERE sr1.numcommande = commandes.numcommande
AND sr1.refclient = clientstype.refclient
GROUP BY annee;
r14 : Affichez par an le montant de l’évolution des paniers de profil type par rapport à
l’année précédente.
FROM
(SELECT substr(date,1,4) as annee, Sum(montant) as
˓→montantTotal
FROM commandes,
(SELECT refclient, numcommande, Sum(quantite * Prix)
˓→AS montant
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY refclient, numcommande) sr1,
clientstype
WHERE sr1.numcommande = commandes.numcommande
AND sr1.refclient = clientstype.refclient
GROUP BY annee) sr1,
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY refclient, numcommande) sr1,
clientstype
WHERE sr1.numcommande = commandes.numcommande
103
Bases de Données MIASHS, Version 1.0
r15 : Affichez par an la difference entre le montant attendu des paniers de profil type et
le montant réalisé
FROM
----------------
(SELECT substr(date,1,4) AS annee, Sum(montant) AS
˓→montantTotal
FROM commandes,
(SELECT refclient, numcommande, Sum(quantite * Prix)
˓→AS montant --9a montant commandes clients
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY refclient, numcommande) sr1,
clientstype
WHERE sr1.numcommande = commandes.numcommande
AND sr1.refclient = clientstype.refclient
GROUP BY annee) sr1,
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY annee) sr2
WHERE sr1.annee = sr2.annee;
r16 : Affichez par an l’évolution de ce differentiel. La requete précédente sera donc utilisée
2 fois.
FROM
(SELECT sr1.annee as annee, (sr2.montant - sr1.
˓→montantTotal) as difference
FROM
----------------
(SELECT substr(date,1,4) AS annee, Sum(montant) AS
˓→montantTotal
FROM commandes,
(SELECT refclient, numcommande, Sum(quantite * Prix)
˓→AS montant --9a montant commandes clients
FROM produits
JOIN commandes ON numproduit = refproduit
104
Bases de Données MIASHS, Version 1.0
FROM commandes,
(SELECT refclient, numcommande, Sum(quantite * Prix)
˓→AS montant --9a montant commandes clients
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY refclient, numcommande) sr1,
clientstype
WHERE sr1.numcommande = commandes.numcommande
AND sr1.refclient = clientstype.refclient
GROUP BY annee) sr1,
105
CHAPITRE 21
Correction Cinema1
select cinema.nomcine
from cinema
order by cinema.nomcine;
r3 : Titres des films avec leur réalisateur, dans l’ordre alphabétique des titres de film
select acteurs.nomacteur
from film, distribution, acteurs
where film.idfilm = distribution.reffilm and
distribution.refacteur = acteurs.idacteur and
film.titre = 'Cop';
r6 : Années de sortie des films tournés avec Gabin dans l’ordre des dates
106
Bases de Données MIASHS, Version 1.0
r10 : Rues, salles et nombres de places des cinémas où sont joués des films sortis en 1984
et dans lesquels joue Delon
r11 : Titres et semaines de programmation des films dans lesquels jouent Deneuve ou
Eastwood
107
Bases de Données MIASHS, Version 1.0
ORDER BY film.titre;
r12 : Pour chaque réalisateur, nom des acteurs qui ont tourné sous sa direction en 1989,
trié par ordre alphabétique de nom de réalisateur puis par ordre alphabétique inverse de
nom d’acteur.
108
CHAPITRE 22
Correction Cinema2
r3 : Afficher pour chaque réalisateur, le nombre de films, en commençant par celui qui a
réalisé le plus de films.
r4 : Afficher pour chaque réalisateur, le nombre de films, pour les réalisateurs qui ont fait
plus d’un film.
109
Bases de Données MIASHS, Version 1.0
r6 : Titre des films qui passaient la semaine 4, avec le nombre de cinémas dans lesquels
ils étaient programmés, limités à ceux programmés dans au moins 4 cinémas, triés dans
l’ordre du nombre de cinémas dans lesquels ils étaient programmés.
r7 : Avec une sous-requête, afficher les films qui ont été tournés la même année que Nikita”
select film.titre
from film
where film.annee = (select film.annee from film where film.
˓→titre = 'Nikita')
r8 : Box office (=les films dans l’ordre décroissant du nombre d’entrées) de la semaine 4
(titre, réalisateur, nombre d’entrées).
r9 : Avec une auto jointure, afficher les films qui ont été tournés la même année que Nikita
select f2.titre
from film f1, film f2
where f1.annee = f2. annee
and f1.titre = 'Nikita'
and f2.titre <> 'Nikita';
r11 : Réalisateurs ayant joué dans des films qu’ils n’ont pas réalisés eux-même
110
Bases de Données MIASHS, Version 1.0
select distinct(acteurs.nomacteur)
from film f1, film f2, distribution, acteurs
where f1.idfilm = distribution.reffilm
and distribution.refacteur = acteurs.idacteur
and acteurs.nomacteur = f2.realisateur
and f1.realisateur <> acteurs.nomacteur;
r12 : Réalisateurs et noms des films précédés dans la programmation par un film dans
lequel joue Pfeiffer
r14 : Liste des acteurs avec le nombre de leurs partenaires (c’est à dire le nombre des
acteurs avec lesquels ils ont joué dans au moins un film), dans l’ordre décroissant du
nombre de partenaires.
r15 : Titre, année et pays des films pour lesquels il existe un film réalisé la même année
dans le même pays.
111
Bases de Données MIASHS, Version 1.0
r16 : Analyse de la concurrence : pour chaque paire de cinémas (C1, C2), nombre de films
identiques programmés simultanément. La liste doit être triée par C1 puis par nombre de
films simultanés (dans l’ordre décroissant), puis par C2.
r17 : Noms des cinémas ayant programmé un même film dans des salles différentes.
r18 : Pour chaque pays, donnez le nombre moyen d’acteurs par film.
r19 : Pour chaque année, noms des cinémas ayant eu à l’affiche tous les films sortis cette
année.
112
CHAPITRE 23
Correction Cinema3
from film
group by decennie;
r3 : les acteurs sont payes 200000 euros et 0.5 euro par entree, calculer le salaire total des
acteurs
select titre
from film left join programme on reffilm = idfilm
where reffilm is null;
113
Bases de Données MIASHS, Version 1.0
select nomcine
from cinema left join
(select refcine from programme where semaine = 4)
on idcine = refcine
where refcine is null;
r8 : films dont le nombre d’entrees est superieur a la moyenne des entrees par semaine
r9 : films dont le nombre d’entrées est égal à +/- 5 % de la moyenne des entrées par
semaine
114
Bases de Données MIASHS, Version 1.0
r10 : les realisateurs sont payes 100000 euros avec une subvention de 50000 euros s’ils
réalisent un film en France, calculer le salaire total des realisateurs
select realisateur,
sum( 100000 + (case when pays = 'France' then 50000
˓→else 0 end)) as salaire
from film
group by realisateur;
r11 : nombre de films par mois et par cinema, on notera Jamais si un cinema ne pro-
gramme aucun film
select nomcine,
(case when semaine is null then 'Jamais'
when semaine <= 4 then 'Janvier'
else 'Fevrier' end) as mois,
count( distinct reffilm ) as nbFilms
from cinema left join programme on refcine = idcine
group by nomcine,mois ;
select sr1.realisateur
from (select count(idfilm)as nb,realisateur from film
˓→group by realisateur) sr1,
select nomacteur
from acteurs,
(select count(nbentrees)as nb,refacteur
from distribution d,programme p
where d.reffilm = P.reffilm
group by refacteur) sr1,
(select max(nb) as nbMax
from (select count(nbentrees) as nb
from distribution d,programme p
where d.reffilm = P.reffilm
group by refacteur))sr2
where sr1.nb = sr2.nbMax and
refacteur = idacteur;
115
Bases de Données MIASHS, Version 1.0
r16 : par cinema liste des films qui ont un nb d’entrées inférieur à la moitié du nb de place
tt salles confondues la semaine 4
r19 : les acteurs ont un intéressement de 0.5 euro par entrée d’un film si le nombre d’en-
trées de ce film dépasse 10000, pour chaque acteur ayant obtenu des intéressements affi-
cher leur montant total
116
Bases de Données MIASHS, Version 1.0
select nomacteur,
sum(nbentrees*(case
when distribution.reffilm in
(select reffilm from programme
group by reffilm having sum(nbentrees) > 10000)
then 0.5 else 0 end)) as interessement
from acteurs, distribution, programme
where idacteur = refacteur
and distribution.reffilm = programme.reffilm
group by nomacteur
having interessement > 0;
r20 : le tarif des entrées des cinémas est de 6 C sauf ‘le melies’ : 5 C et ‘le club’ : 3 C. Quelle
est la recette totale des cinemas
select nomcine,
sum(nbentrees)*(case
when nomcine = 'le melies' then 5
when nomcine = 'le club' then 3
else 8 end)as recette
from cinema, programme
where refcine = idcine
group by nomcine;
r21 : pour ‘le club’, par salle et par film, afficher ‘abandonner’ si le taux d’occupation de
la semaine 4 est inférieur à 20% des places de la salle, ‘ouvrir’ s’il est supérieur à 80%
sinon ‘continuer’
select p.salle,titre,
(case when (nbentrees*100)/(7* nbplaces) < 20 then
˓→'abandonner'
r22 : par cinema et par semaine, liste des salles sans programmation
117
Bases de Données MIASHS, Version 1.0
r23 : acteurs qui n’ont pas tourné de films au USA mais qui en ont tourné en Espagne
118