Vous êtes sur la page 1sur 122

Bases de Données MIASHS

Version 1.0

Alain Taquet

Septembre 2017
Table des matières

1 CM1 : Création d’une base de données 1


1.1 Cardinalités . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 La base Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2.1 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2.2 Relations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.3 LDD et LMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.3.1 Création de tables (LDD) . . . . . . . . . . . . . . . . . . . . . . . . 1
1.3.2 Insertion et modification de données (LMD) . . . . . . . . . . . . . . 2
1.4 Création de la base exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2 CM2 : Selection sur une seule table 5


2.1 La clause SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.1 Projection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.2 Lignes distinctes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.3 Champs calculés - alias . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 La clause WHERE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2.1 Filtrage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.2 Caractères génériques . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.3 Valeurs nulles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3 La clause ORDER BY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.4 Expressions et Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.4.1 Opérations sur les chaines de caractères . . . . . . . . . . . . . . . . 11
2.4.2 Opérateur conditionnel . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4.3 Marqueur Null . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4.4 Fonctions statistiques . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3 CM3 : Selections utilisant plusieurs tables 16


3.1 Existence d’association . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.1.1 Emboitement des requêtes . . . . . . . . . . . . . . . . . . . . . . . 16
3.1.2 Emboitement à plusieurs niveaux . . . . . . . . . . . . . . . . . . . . 17
3.1.3 Références à la même table . . . . . . . . . . . . . . . . . . . . . . . 18
3.2 Conditions sur les sous requêtes . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.3 Sous requêtes corrélées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.4 Une requête courante : la division . . . . . . . . . . . . . . . . . . . . . . . . 20

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

7 TD2 : Selection sur une seule table 44

8 TD3 : Selections utilisant plusieurs tables 48

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

15 Correction CM6 : Exercices 71

16 Correction TD2 : Selection sur une seule table 79

17 Correction TD3 : Selections utilisant plusieurs tables 83

18 Correction TD4 : Jointures 88

ii
19 Correction TD5 : Regroupements 92

20 Correction TD6 : Synthèse 97

21 Correction Cinema1 106

22 Correction Cinema2 109

23 Correction Cinema3 113

iii
CHAPITRE 1

CM1 : Création d’une base de données

1.1 Cardinalités

MLD, Diagramme d’instances, Cardinalités, MCD


Exemples :
– Des étudiants pratiquent un et un seul sport (1-n)
– Des étudiants pratiquent plusieurs sports (n-n)

1.2 La base Exemple

La base exemple se trouve ici : exemple.s3db .

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

1.3 LDD et LMD

1.3.1 Création de tables (LDD)

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

1.3.2 Insertion et modification de données (LMD)

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 ;

1.4 Création de la base exemple

- Table regions

CREATE TABLE "regions" (


"coderegion" INTEGER NOT NULL,
"region" TEXT NOT NULL,
PRIMARY KEY("coderegion")
);

INSERT INTO "regions" VALUES ('1', 'nord');

1.4. Création de la base exemple 2


Bases de Données MIASHS, Version 1.0

# coderegion region
1 1 nord
2 2 sud
3 3 centre
4 4 corse
- Table villes

CREATE TABLE "villes" (


"codepostal" TEXT NOT NULL,
"ville" TEXT NOT NULL,
"coderegion" INTEGER NOT NULL,
PRIMARY KEY("codepostal"),
FOREIGN KEY ("coderegion") REFERENCES "regions" ("coderegion")
);

INSERT INTO "villes" VALUES ('59000', 'Lille', '1');

# codepostal ville coderegion


1 59000 Lille 1
2 26200 Montelimar 2
3 75000 Paris 3
4 59800 Lille 1
5 59100 Roubaix 1
- Table personnes

CREATE TABLE "personnes" (


"codepersonne" INTEGER NOT NULL,
"nom" TEXT,
"salaire" INTEGER NOT NULL,
"codepostal" TEXT,
"responsable" INTEGER,
PRIMARY KEY("codepersonne"),
FOREIGN KEY ("codepostal") REFERENCES "villes" ("codepostal"),
FOREIGN KEY ("responsable") REFERENCES "personnes" (
˓→"codepersonne")

);

INSERT INTO "personnes" VALUES ('1', 'Amelmou', '30000', '59000',


˓→null);

# codepersonne nom salaire codepostal responsable


1 1 Amelmou 30000 59000
2 2 Alavie 20000 59800 1
3 3 Ancieux 15000 26200 4
4 4 Tete 40000 59000
- Table interventions

CREATE TABLE "interventions" (


"codepersonne" INTEGER NOT NULL,

1.4. Création de la base exemple 3


Bases de Données MIASHS, Version 1.0

"coderegion" INTEGER NOT NULL,


PRIMARY KEY("codepersonne","coderegion"),
FOREIGN KEY ("codepersonne") REFERENCES "personnes" (
˓→"codepersonne"),

FOREIGN KEY ("coderegion") REFERENCES "regions" ("coderegion")


);

INSERT INTO "interventions" VALUES ('1', '1');

# 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

CREATE TABLE "salaires" (


"min" INTEGER,
"max" INTEGER,
"tranche" TEXT NOT NULL,
PRIMARY KEY("tranche")
);

INSERT INTO "salaires" VALUES ('10000', '20000', 'C');

# min max tranche


1 10000 20000 C
2 20000 30000 B
3 30000 50000 A
4 0 10000 D

1.4. Création de la base exemple 4


CHAPITRE 2

CM2 : Selection sur une seule table

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.

2.1 La clause SELECT

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.

SELECT T.x, T.y


FROM T;

5
Bases de Données MIASHS, Version 1.0

2.1.1 Projection

- Afficher les noms et salaires des personnes dans la base

SELECT nom, salaire


FROM personnes;

# 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;

# codepostal ville coderegion


1 59000 Lille 1
2 26200 Montelimar 2
3 75000 Paris 3
4 59800 Lille 1
5 59100 Roubaix 1

2.1.2 Lignes distinctes

- Afficher les codes postaux des personnes

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;

- Pour n’avoir qu’un seule fois les code postaux :

SELECT DISTINCT codepostal


FROM personnes;

2.1. La clause SELECT 6


Bases de Données MIASHS, Version 1.0

# codepostal
1 59000
2 59800
3 26200

2.1.3 Champs calculés - alias

On peut faire des opérations

SELECT 1 + 1;

- Afficher le salaire net des personnes : salaire * 0,8

SELECT nom, salaire * 0.80


FROM personnes;

# nom salaire * 0.80


1 Amelmou 24000.0
2 Alavie 16000.0
3 Ancieux 12000.0
4 Tete 32000.0
On peut nommer (ou renommer) les colonnes avec AS :

SELECT x AS y
FROM T;

- Renommer le nom en salarie et le salaire net en salaireNet

SELECT nom AS salarie, salaire * 0.80 AS salaireNet


FROM personnes;

# salarie salaireNet
1 Amelmou 24000.0
2 Alavie 16000.0
3 Ancieux 12000.0
4 Tete 32000.0

2.2 La clause WHERE

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. La clause WHERE 7


Bases de Données MIASHS, Version 1.0

2.2.1 Filtrage

- Afficher les noms des personnes qui gagnent plus de 15000 C.

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;

- Nom des personnes qui ne gagnent pas entre 20 000 et 30 000 C

SELECT nom
FROM personnes
WHERE salaire NOT BETWEEN 20000 AND 30000;

# nom
1 Ancieux
2 Tete

2.2.2 Caractères génériques

L’opérateur LIKE permet de faire des recherches en utilisant un modèle.

2.2. La clause WHERE 8


Bases de Données MIASHS, Version 1.0

– % : n’importe-quelle suite de caractères (éventuellement vide)


– _ : n’importe-quel caractère (exactement un)
On utilise ce modèle avec LIKE et pas l’égalité (sinon vous cherchez le caractère %) :

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

2.2.3 Valeurs nulles

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;

- Afficher les noms des personnes qui n’ont pas de responsable.

SELECT nom
FROM personnes
WHERE responsable IS NULL;

# nom
1 Amelmou
2 Tete

2.2. La clause WHERE 9


Bases de Données MIASHS, Version 1.0

2.3 La clause ORDER BY

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;

- Afficher les noms des personnes dans l’ordre croissant

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

SELECT codepostal, nom


FROM personnes
ORDER BY codepostal ASC, nom DESC;

# 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 :

2.3. La clause ORDER BY 10


Bases de Données MIASHS, Version 1.0

- Afficher les noms et les salaires net des personnes dans l’ordre croissant des salaires net puis
des noms

SELECT nom, salaire * 0.8 AS salaireNet


FROM personnes
ORDER BY salaireNet, nom;

# nom salaireNet
1 Ancieux 12000.0
2 Alavie 16000.0
3 Amelmou 24000.0
4 Tete 32000.0

2.4 Expressions et Fonctions

2.4.1 Opérations sur les chaines de caractères

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

SELECT DISTINCT substr(codepostal,1,2) AS departement


FROM 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

SELECT upper(substr(nom,1,1)) || lower(substr(nom,2)) as Nom


FROM personnes;

2.4. Expressions et Fonctions 11


Bases de Données MIASHS, Version 1.0

# Nom
1 Amelmou
2 Alavie
3 Ancieux
4 Tete

2.4.2 Opérateur conditionnel

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;

2.4. Expressions et Fonctions 12


Bases de Données MIASHS, Version 1.0

# 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

2.4.3 Marqueur Null

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”

2.4. Expressions et Fonctions 13


Bases de Données MIASHS, Version 1.0

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 :

SELECT nom, coalesce(responsable, "Directeur") as responsable


FROM personnes;

2.4.4 Fonctions statistiques

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.

SELECT count(*) AS nbpersonnes,


avg(salaire) AS moysalaire,
max(salaire) - min(salaire) AS ecart
FROM personnes;

# nbpersonnes moysalaire ecart


1 4 26250.0 25000

2.4. Expressions et Fonctions 14


Bases de Données MIASHS, Version 1.0

- On peut effectuer des calculs sur les champs : calculer la moyenne des salaires nets

SELECT avg(salaire * 0.8) AS moysalaire


FROM personnes;

# 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 ...)

SELECT count(distinct coderegion) as nb


FROM interventions;

# 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

SELECT count(codepersonne) - count(responsable) AS nbdirecteurs


FROM personnes;

# nbdirecteurs
1 2
- Calculer le nombre de personnes et le maximum des salaires qui ont pour nom “personne”

SELECT count(codepersonne) AS nbpers, max(salaire) AS maxsal


FROM personnes
WHERE nom = 'personne';

# nbpers maxsal
1 0
On trouve 0 pour nbpers et null pour maxsal

2.4. Expressions et Fonctions 15


CHAPITRE 3

CM3 : Selections utilisant plusieurs tables

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.

3.1 Existence d’association

3.1.1 Emboitement des requêtes

Pour executer une requete il est necessaire de creer une sous requete qui donne un resultat
intermédiaire utilisé dans une requête englobante

SELECT x FROM T1 WHERE y IN (


SELECT a FROM T2 WHERE b );

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');

3.1.2 Emboitement à plusieurs niveaux

On peut emboiter autant de reqûete que l’on veut


- Afficher les noms des personnes de la région nord. Il faut d’abord déterminer le code de la
région nord, puis leurs code postaux et enfin les noms de personnes.

SELECT nom
FROM personnes
WHERE codepostal IN (
SELECT codepostal
FROM villes
WHERE coderegion IN (
SELECT coderegion
FROM regions
WHERE region = 'nord'));

3.1. Existence d’association 17


Bases de Données MIASHS, Version 1.0

# nom
1 Amelmou
2 Alavie
3 Tete

3.1.3 Références à la même table

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)

SELECT distinct ville


FROM villes
WHERE coderegion = (
SELECT coderegion
FROM villes
WHERE ville = 'Lille')
AND ville != '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.

3.2 Conditions sur les sous requêtes

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

SELECT nom FROM personnes


WHERE salaire >= (
SELECT avg(salaire)
FROM personnes);

# nom
1 Amelmou
2 Tete

3.2. Conditions sur les sous requêtes 18


Bases de Données MIASHS, Version 1.0

3.3 Sous requêtes corrélées

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.

SELECT region FROM regions


WHERE (SELECT count(codepersonne)
FROM interventions
WHERE regions.coderegion = interventions.coderegion) >= 2;

# 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.

SELECT nom FROM personnes P


WHERE salaire >= (
SELECT avg(salaire)
FROM personnes
WHERE substr(P.codepostal,1,2) = substr(codepostal,1,2));

# nom
1 Amelmou
2 Ancieux
3 Tete
Attention à l’erreur suivante : ici on renomme la table personnes de la sous requête :

SELECT nom FROM personnes


WHERE salaire >= (

3.3. Sous requêtes corrélées 19


Bases de Données MIASHS, Version 1.0

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 !

3.4 Une requête courante : la division

- Afficher les noms des personnes qui interviennent ds tt les regions

SELECT nom FROM personnes P


WHERE
(SELECT count(coderegion)
FROM interventions
WHERE P.codepersonne = codepersonne) =
(SELECT count(*) FROM regions);

# 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.

3.5 Non existence d’associations

On cherche ici les lignes qui ne remplissent pas un critère

SELECT x FROM T1 WHERE y NOT IN (


SELECT a FROM T2 WHERE b );

- Nom des personnes qui n’interviennent pas dans la region 1

SELECT nom
FROM personnes
WHERE codepersonne NOT IN (
SELECT codepersonne
FROM interventions
WHERE coderegion = 1);

# nom
1 Ancieux
2 Tete

3.4. Une requête courante : la division 20


Bases de Données MIASHS, Version 1.0

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

3.5. Non existence d’associations 21


CHAPITRE 4

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.

4.1 Jointure croisée

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

- Produit cartésien des tables villes et personnes

SELECT ville, nom


FROM villes, personnes

# 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

4.2 Jointure interne

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.

SELECT ville, nom


FROM villes, personnes
WHERE villes.codepostal = personnes.codepostal
ORDER BY ville;

# 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.

4.2.1 Avec condition de selection

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;

- Afficher les villes et noms des personnes de la région de code 1.

SELECT ville, nom


FROM villes, personnes
WHERE villes.codepostal = personnes.codepostal
AND coderegion = 1;

4.2. Jointure interne 23


Bases de Données MIASHS, Version 1.0

# 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.

SELECT DISTINCT V2.ville


FROM villes V1, villes V2
WHERE V1.coderegion = V2.coderegion
AND V1.ville = 'Roubaix'
AND V2.ville != 'Roubaix';

# ville
1 Lille

4.2.3 Sous requêtes

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

4.2. Jointure interne 24


Bases de Données MIASHS, Version 1.0

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

SELECT DISTINCT ville FROM villes


WHERE coderegion = (SELECT coderegion FROM villes WHERE ville =
˓→'Roubaix')

AND ville != 'Roubaix';

# ville
1 Lille
- Même question avec une jointure

SELECT DISTINCT ville FROM villes V,


(SELECT coderegion FROM villes WHERE ville = 'Roubaix') Rbx
WHERE V.coderegion = Rbx.coderegion
AND ville != 'Roubaix';

# ville
1 Lille

4.2.4 Jointures généralisées

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 des personnes qui gagnent plus que Alavie

SELECT nom FROM personnes,


(SELECT salaire FROM personnes WHERE nom = 'Alavie') salAlavie
WHERE personnes.salaire > salAlavie.salaire;

# nom
1 Amelmou
2 Tete
- nom et tranche des salaires des personnes

SELECT nom, tranche


FROM personnes, salaires
WHERE salaire >= min
AND salaire < max;

4.2. Jointure interne 25


Bases de Données MIASHS, Version 1.0

# nom tranche
1 Amelmou A
2 Alavie B
3 Ancieux C
4 Tete A

4.3 Opérateurs de jointure

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;

-- avec plusieurs conditions


SELECT x
FROM T1 JOIN T2
ON T1.a = T2.b AND T1.c = T2.d;

-- avec sous requete


SELECT x
FROM T1 JOIN (SELECT ...) T2 ON T1.a = T2.b;

-- jointure externe LEFT ou RIGHT


SELECT x
FROM T1 LEFT JOIN T2 ON T1.a = T2.b;

On peut écrire la requête précédente avec une jointure interne :


Pour chaque ville afficher les noms des personnes

SELECT ville, nom


FROM villes
JOIN personnes ON villes.codepostal = personnes.codepostal;

- Pour chaque personne afficher sa région

SELECT nom, region


FROM personnes P
JOIN villes V ON P.codepostal = V.codepostal
JOIN regions R ON R.coderegion = V.coderegion;

4.3. Opérateurs de jointure 26


Bases de Données MIASHS, Version 1.0

# 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

4.4 Jointure externe

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 :

SELECT region, ville


FROM regions
JOIN villes ON regions.coderegion = villes.coderegion;

# 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.

SELECT region, ville


FROM regions
JOIN villes ON regions.coderegion = villes.coderegion;

4.4. Jointure externe 27


Bases de Données MIASHS, Version 1.0

# 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

SELECT P.nom, R.nom AS responsable


FROM personnes P LEFT JOIN personnes R
ON P.responsable = R.codepersonne

# 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

4.4. Jointure externe 28


Bases de Données MIASHS, Version 1.0

- Afficher les régions 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

4.5 Utilité de la jointure croisée

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.

SELECT x, y FROM T1 JOIN T2


LEFT JOIN T3 ON conditions
WHERE conditions;

– pour chaque code de personne afficher les codes des regions dans lesquelles ils n’inter-
viennent pas

SELECT P.codepersonne, R.coderegion


FROM personnes P
JOIN regions R

4.5. Utilité de la jointure croisée 29


Bases de Données MIASHS, Version 1.0

LEFT JOIN interventions I ON


P.codepersonne = I.codepersonne
AND R.coderegion = I.coderegion
WHERE I.codepersonne is null;

# 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’ :

SELECT codepersonne, coderegion


FROM personnes P, regions R
WHERE codepersonne|| '-'|| coderegion NOT IN
(SELECT codepersonne|| '-'|| coderegion
FROM interventions);

- pour chaque nom de personne afficher les noms des regions dans lesquelles ils n’interviennent
pas

SELECT nom, region


FROM personnes P JOIN
(SELECT P.codepersonne AS codepersonne, R.coderegion AS coderegion
FROM personnes P
JOIN regions R
LEFT JOIN interventions I ON
P.codepersonne = I.codepersonne
AND R.coderegion = I.coderegion
WHERE I.codepersonne is null) sr1
ON P.codepersonne = sr1.codepersonne
JOIN regions R ON R.coderegion = sr1.coderegion;

4.5. Utilité de la jointure croisée 30


Bases de Données MIASHS, Version 1.0

# 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.

4.5. Utilité de la jointure croisée 31


CHAPITRE 5

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.

5.1 La clause GROUP BY

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.

SELECT coderegion, ville


FROM villes
ORDER BY coderegion;

# 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

SELECT coderegion, count(ville) as nbvilles


FROM villes
GROUP BY coderegion
ORDER BY coderegion;

# 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

SELECT coderegion, count(*) as nbvilles


FROM villes
GROUP BY coderegion
ORDER BY coderegion;

# 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)

SELECT coderegion, count(distinct ville) as nbvilles


FROM villes
GROUP BY coderegion
ORDER BY coderegion;

# coderegion nbvilles
1 1 2
2 2 1
3 3 1

5.2 Sémantique du GROUP BY

On commence par faire la requête sans GROUP BY avec les conditions dans le WHERE.

5.2. Sémantique du GROUP BY 33


Bases de Données MIASHS, Version 1.0

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

SELECT substr(codepostal,1,2) AS dpt, count(*) AS nb


FROM personnes
GROUP BY dpt;

# dpt nb
1 26 1
2 59 3

5.3 GROUP BY HAVING

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.

SELECT x, fonction(y) AS resultat


FROM T
WHERE condition sur x
GROUP BY x
HAVING condition sur resultat

– 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

SELECT codepersonne, count(*) AS nb


FROM interventions
WHERE coderegion in (1,2)
GROUP by codepersonne;

# codepersonne nb
1 1 2
2 2 1
3 3 1
4 4 1

5.3. GROUP BY HAVING 34


Bases de Données MIASHS, Version 1.0

– 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

SELECT codepersonne, count(*) AS nb


FROM interventions
WHERE coderegion in (1,2)
GROUP BY codepersonne
HAVING nb >= 2;

# 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

SELECT substr(codepostal,1,2) AS dpt


FROM personnes
GROUP BY dpt
HAVING count(*) >= 2;

# dpt
1 59
- Afficher les departements avec au moins 2 personnes ainsi que le nombre de personnes

SELECT substr(codepostal,1,2) AS dpt, count(*) AS nb


FROM personnes
GROUP BY dpt
HAVING nb >= 2;

# dpt nb
1 59 3
- Afficher les departements avec au moins 2 personnes qui gagnent au moins 20000C

SELECT substr(codepostal,1,2) AS dpt


FROM personnes
WHERE salaire >= 20000
GROUP BY dpt
HAVING count(*) >= 2;

# dpt
1 59

5.3. GROUP BY HAVING 35


Bases de Données MIASHS, Version 1.0

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.

SELECT region, count(*) as nb


FROM regions R, interventions I
WHERE R.coderegion = I.coderegion
GROUP BY region
HAVING nb >= 2
ORDER BY nb desc;

# 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.

SELECT p1.nom, count(*) - 1 AS nb


FROM personnes p1, personnes p2
WHERE p2.salaire >= p1.salaire
GROUP BY p1.nom;

# 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.

SELECT region, tranche, count(*) AS nb


FROM personnes P
JOIN villes V ON P.codepostal = V.codepostal
JOIN regions R ON V.coderegion = R.coderegion
JOIN salaires S ON salaire >= min
AND salaire < max
GROUP BY region, tranche;

# 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

5.3. GROUP BY HAVING 36


Bases de Données MIASHS, Version 1.0

- 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

5.3. GROUP BY HAVING 37


Bases de Données MIASHS, Version 1.0

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

5.4 Groupement avec jointure externe

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

SELECT ville, count(codepersonne) AS nb


FROM villes V LEFT JOIN personnes P ON P.codepostal = V.codepostal
GROUP BY ville;

– attention à ne pas écrire

SELECT ville, count(*) AS nb -- ERREUR


FROM villes V LEFT JOIN personnes P ON P.codepostal = V.codepostal
GROUP BY ville;

5.4. Groupement avec jointure externe 38


CHAPITRE 6

CM6 : Exercices

6.1 Quelques précisions sur null et IN

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) :

SELECT count(B), sum(B), max(B), avg(B) FROM U;

# count(B) sum(B) max(B) avg(B)


1 2 6 4 3
S’il n’y a aucune valeur qui soit différente de null le résultat est null :

SELECT sum(B) FROM U WHERE A = 3;

# sum(B)
1 null
Par contre effectuer une opération avec null donne null :

SELECT A + B FROM U WHERE A = 3;

# A+B
1 null
Les opérateurs logiques produisent null également :

SELECT A FROM U WHERE A = 3 AND A > B;


-- il n'y a aucun résultat

# A

On peut tester si A > B est null avec is null (pas = null)

SELECT A FROM U WHERE A = 3 AND A > B is null;

# 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

SELECT X FROM T WHERE X IN (SELECT X FROM T);


-- ou bien :
SELECT X FROM T WHERE X IN (1,2,3,3);

# 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

SELECT X FROM T WHERE X IN (SELECT DISTINCT X FROM T);


-- ou bien :
SELECT X FROM T WHERE X IN (1,2,3);

# 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 :

SELECT DISTINCT X FROM T WHERE X IN (1,2,3); -- ou (1,2,3,3)

# X
1 1
2 2
3 3

6.2 La base

La base se trouve ici : cm6.s3db .


On dispose des tables suivantes :
– Table “T”
# X Y
1 1 4
2 2 2
3 3 2
4 3 1
– Table “U”

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

Que produisent les requêtes suivantes ?


r1 :

SELECT * FROM T WHERE X > 2;

r2 :

SELECT A FROM U ORDER BY B;

r3 :

SELECT A * B FROM U;

r4 :

SELECT DISTINCT Y FROM T ORDER BY Y - X;

r5 :

SELECT X, A FROM T LEFT JOIN U ON Y = B;

r6 :

SELECT A - X FROM T JOIN U ON X = B;

r7 :

SELECT SUM(A) FROM U;

r8 :

SELECT DISTINCT COUNT(Y) FROM T GROUP BY X;

r9 :

SELECT SUM(B) FROM T, U;

r10 :

SELECT SUM(B) FROM T, U GROUP BY A;

r11 :

6.3. Questions 41
Bases de Données MIASHS, Version 1.0

SELECT SUM(Y) FROM T GROUP BY Y;

r12 :

SELECT SUM(X * B) FROM T, U GROUP BY B - A;

r13 :

SELECT X FROM T WHERE X IN (SELECT A FROM U);

r14 :

SELECT X FROM T WHERE X IN


(SELECT A FROM U WHERE B IN (SELECT Y FROM T));

r15 :

SELECT X FROM T WHERE X IN (SELECT Y FROM T);

r16 :

SELECT A FROM U WHERE A > (SELECT MIN(B) FROM U);

r17 :

SELECT X FROM T T1
WHERE (SELECT SUM(Y) FROM T
WHERE T1.X = X) > (SELECT B FROM U WHERE A = X);

r18 :

SELECT X FROM T WHERE MAX(X-Y, Y-X) IN (SELECT A FROM U);

r19 :

SELECT A FROM U JOIN (SELECT X - Y AS S FROM T) ON B = S;

r20 :

SELECT DISTINCT A FROM U, (SELECT X-Y AS S FROM T)


WHERE S < B;

r21 :

SELECT A FROM U WHERE B =


(SELECT MAX(Y) FROM T, U WHERE X = A);

r22 :

SELECT MIN(T.Y) FROM T, (SELECT MAX(X) AS M,Y FROM T GROUP


˓→BY Y) SR

WHERE M > SR.Y AND SR.Y = X;

6.3. Questions 42
Bases de Données MIASHS, Version 1.0

r23 :

SELECT T1.X, COUNT(T1.X) FROM T T1, T T2


WHERE T2.Y > T1.Y GROUP BY T1.X;

r24 :

SELECT X, COUNT(B) FROM T,U


WHERE X = A GROUP BY X;

r25 :

SELECT DISTINCT(T.Y) FROM T JOIN (SELECT B, X FROM U LEFT


˓→JOIN T ON B = Y) SR

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

WHERE nb = maxNb AND X = A;

6.3. Questions 43
CHAPITRE 7

TD2 : Selection sur une seule table

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

Champs calculés : 10 à 14 sauf la 13


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
# nom
1 Monkey
2 Ninja baby
3 Diamond lady
r12 : Afficher les noms et le prix HT des produits dans l’ordre croissant des prix HT (tva
de 20%)
# nom HT
1 Tube-stick indice 4 40.8333333333333
2 Tube-stick indice 8 40.8333333333333
3 Tube-stick indice 15 41.6666666666667
. . .
31 Nepal top 1208.33333333333
r13 : Afficher les noms, le prix HT, le montant de la TVA et le prix TTC des produits dans
l’ordre des noms
# nom HT TVA TTC
1 Alpinist 729.166666666667 145.833333333333 875
2 Aventure 65 790.833333333333 158.166666666667 949
3 Charlotte 120.0 24.0 144
. . . . .
31 canard 120.0 24.0 144
r14 : Afficher les départements des clients dans l’ordre croissant
# dpt
1 01
2 02
3 13
. .
17 93
r15 : Afficher les années des dates des commandes de la base
# anneesCommandes
1 1995
2 1996
3 1997
Fonctions statistiques.
r16 : Affichez le nombre de produits dans la base.
# nb
1 31
r17 : Affichez le maximum, le minimum et la moyenne des prix des produits.
# maxPrix minPrix moyPrix
1 1450 49 461.096774193548
r18 : Affichez le nombre d’articles vendus.

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

TD3 : Selections utilisant plusieurs tables

r1 : Affichez les noms des clients de Lille


# nom
1 Deulisse
2 Peuleurido
3 Attan
. .
14 Yoraitoux
r2 : Affichez les noms des clients de Lille et Roubaix
# nom
1 Alavie
2 Deulisse
3 Peuleurido
. .
27 Yoraitoux
r3 : Afficher les noms des clients dont le nom commence par Ta et qui ont effectué une
commande
# nom
1 Talonion
2 Tabille
3 Taijouhai Parmillier
r4 : Afficher le nom du client qui a effectué la commande 1
# nom
1 Alavie
r5 : Afficher les noms des clients qui ont effectué une commande en janvier 1997
# nom
1 Alavie
2 Aulet
3 Talonion
. .
10 Adlaplace
r6 : Affichez les noms des produits de prix supérieur à la moyenne des prix

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

# nom sansReduc Reduc avecReduc


1 Diamond lady 1650 165.0 1485.0
2 Aventure 65 949 0 949
3 Super guide tradition 1312 0 1312
4 Charlotte 144 0 144
r13 : Afficher le montant de la commande 1 en tenant compte de la réduction de la ques-
tion précédente
# montant
1 3890.0
r14 : Affichez par ordre alphabétique les noms des clients qui n’ont rien commandé
# nom
1 Adessin
2 Adlvy Yadlespoir
3 Adonaideux
. .
477 Zieubleux
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é
# nom prenom minPrix
1 Duman Mariette 1045
2 Comaindieu Thibaut
3 Adessin Blanche
. . . .
485 Céjoli Edouard Nehneh

53
CHAPITRE 10

TD5 : Regroupements

r1 : Affichez le nombre de produits par marque (sans la valeur 0)


# nom nbProduits
1 Boreal 1
2 Climbing shoes 1
3 EB 1
. . .
23 vertical 1
r2 : Affichez le nombre de produits par marque avec la valeur 0
# nom nbProduits
1 Boreal 1
2 Climbing shoes 1
3 EB 1
. . .
26 vertical 1
r3 : Affichez le nombre de produits par catégorie
# nom nbProduits
1 Chaussons d_escalade 6
2 Chaussures d_alpinisme 6
3 Lunettes de glacier 4
. . .
6 Vetements de grimpe 4
r4 : Affichez le nombre de produits vendus par catégorie
# nom nbProduits
1 Chaussons d_escalade 61
2 Chaussures d_alpinisme 75
3 Lunettes de glacier 41
. . .
6 Vetements de grimpe 45
r5 : Affichez le nombre de commandes par an
# annee nbCommandes
1 1995 12
2 1996 71
3 1997 37

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

– La base Cinema se trouve ici : cinema.s3db .

12.2 Questions

r1 : Afficher les noms des cinémas dans l’ordre alphabétique


# nomcine
1 gaumont
2 la nef
3 le club
. .
10 vox
r2 : Titre, année de sortie et réalisateur des films français

60
Bases de Données MIASHS, Version 1.0

# titre annee realisateur


1 La baie des anges 1962 Demy
2 Mon cher sujet 1989 Mieville
3 Baxter 1989 Boivin
. . . .
14 Les visiteurs 1993
3. Clavier

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

r1 : nb de films par acteur


# nomacteur nbFilms
1 Bueno 1
2 Clarkson 1
3 Cleese 1
. . .
34 Woods 1
r2 : Afficher pour le réalisateur Mieville, le nombre de films, en nommant nbreFilms le
titre de la colonne.
# nbreFilms
1 1
r3 : Afficher pour chaque réalisateur, le nombre de films, en commençant par celui qui a
réalisé le plus de films.
# realisateur nbFilms
1 Parker 3
2 Besson 2
3 Carne 2
. . .
27 Stone 1
r4 : Afficher pour chaque réalisateur, le nombre de films, pour les réalisateurs qui ont fait
plus d’un film.
# realisateur nbFilms
1 Besson 2
2 Carne 2
3 Coppola 2
. . .
5 Truffaut 2
r5 : Nombre de semaines de programmation de chaque film.

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

r1 : films qui ont au moins 6 acteurs


# reffilm count(refacteur)
1 8 6
r2 : nombre de films par decennie
# decennie nbFilms
1 30 1
2 40 1
3 60 3
. . .
6 90 8
r3 : les acteurs sont payes 200000 euros et 0.5 euro par entree, calculer le salaire total des
acteurs
# nomacteur salaire
1 Bueno 201360.0
2 Clarkson 201758.5
3 Cleese 208952.5
. . .
34 Woods 203754.0
r4 : pourcentage de remplissage des salles du cinema gaumont la semaine 4
# salle pourcentage
1 1 9
2 2 51
3 3 47
. . .
6 6 41
r5 : films qui n’ont pas ete programmes

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

r15 : realisateurs qui ne sont pas acteurs avec 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

Correction CM6 : Exercices

r1 :

SELECT * FROM T WHERE X > 2;

== === ====
# X Y
== === ====
1 3 2
2 3 1
== === ====

r2 :

SELECT A FROM U ORDER BY B;

== =====
# 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 :

SELECT DISTINCT Y FROM T ORDER BY Y - X;

== =====
# Y
== =====
1 1
2 2
3 4
== =====

r5 :

SELECT X, A FROM T LEFT JOIN U ON Y = B;

== === ====
# X A
== === ====
1 1 2
2 2 1
3 3 1
4 3
== === ====

r6 :

SELECT A - X FROM T JOIN U ON X = B;

== ========
# A - X
== ========
1 -1
== ========

r7 :

SELECT SUM(A) FROM U;

== =========
# SUM(A)
== =========
1 6
== =========

r8 :

72
Bases de Données MIASHS, Version 1.0

SELECT DISTINCT COUNT(Y) FROM T GROUP BY X;

== ===========
# COUNT(Y)
== ===========
1 1
2 2
== ===========

r9 :

SELECT SUM(B) FROM T, U;

== =========
# SUM(B)
== =========
1 24
== =========

r10 :

SELECT SUM(B) FROM T, U GROUP BY A;

== =========
# SUM(B)
== =========
1 8
2 16
3
== =========

r11 :

SELECT SUM(Y) FROM T GROUP BY Y;

== =========
# SUM(Y)
== =========
1 1
2 4
3 4
== =========

r12 :

SELECT SUM(X * B) FROM T, U GROUP BY B - A;

73
Bases de Données MIASHS, Version 1.0

== =============
# SUM(X * B)
== =============
1
2 18
3 36
== =============

r13 :

SELECT X FROM T WHERE X IN (SELECT A FROM U);

== =====
# X
== =====
1 1
2 2
3 3
4 3
== =====

r14 :

SELECT X FROM T WHERE X IN


(SELECT A FROM U WHERE B IN (SELECT Y FROM T));

== =====
# X
== =====
1 1
2 2
== =====

r15 :

SELECT X FROM T WHERE X IN (SELECT Y FROM T);

== =====
# X
== =====
1 1
2 2
== =====

r16 :

74
Bases de Données MIASHS, Version 1.0

SELECT A FROM U WHERE A > (SELECT MIN(B) FROM U);

== =====
# 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 :

SELECT X FROM T WHERE MAX(X-Y, Y-X) IN (SELECT A FROM U);

== =====
# X
== =====
1 1
2 3
3 3
== =====

r19 :

SELECT A FROM U JOIN (SELECT X - Y AS S FROM T) ON B = S;

== =====
# A
== =====
1 1
== =====

r20 :

SELECT DISTINCT A FROM U, (SELECT X-Y AS S FROM T)


WHERE S < B;

75
Bases de Données MIASHS, Version 1.0

== =====
# A
== =====
1 1
2 2
== =====

r21 :

SELECT A FROM U WHERE B =


(SELECT MAX(Y) FROM T, U WHERE X = A);

== =====
# A
== =====
1 2
== =====

r22 :

SELECT MIN(T.Y) FROM T, (SELECT MAX(X) AS M,Y FROM T GROUP


˓→BY Y) SR

WHERE M > SR.Y AND SR.Y = X;

== ===========
# MIN(T.Y)
== ===========
1 2
== ===========

r23 :

SELECT T1.X, COUNT(T1.X) FROM T T1, T T2


WHERE T2.Y > T1.Y GROUP BY T1.X;

== === =============
# X COUNT(T1.X)
== === =============
1 2 1
2 3 4
== === =============

r24 :

SELECT X, COUNT(B) FROM T,U


WHERE X = A GROUP BY X;

76
Bases de Données MIASHS, Version 1.0

== === ==========
# X COUNT(B)
== === ==========
1 1 1
2 2 1
3 3 0
== === ==========

r25 :

SELECT DISTINCT(T.Y) FROM T JOIN (SELECT B, X FROM U LEFT


˓→JOIN T ON B = Y) SR

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

WHERE nb = maxNb AND X = A;

== =====
# B
== =====

77
Bases de Données MIASHS, Version 1.0

1 2
== =====

78
CHAPITRE 16

Correction TD2 : Selection sur une seule table

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.

select nom, prenom


from clients
where nom like 'Ta%';

r3 : Recherchez les clients dont le nom commence par Ta et dont le code postal est 59100

select nom, prenom


from clients
where nom like 'Ta%'
and codepostal = '59100';

r4 : Recherchez les clients dont le nom commence par Ta et qui habitent le Nord

select nom, prenom


from clients
where nom like 'Ta%'
and codepostal like '59%';

r5 : Recherchez les clients dont le nom commence par Ta et qui habitent le Nord ou le Pas
de Calais

select nom, prenom


from clients
where nom like 'Ta%'
and (codepostal like '59%'
or codepostal like '62%');

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

select nom, prenom


from clients
where nom like 'Ta%'
and codepostal not like '59%'
and codepostal not like '62%';

r7 : Affichez les numéros de tous les produits dans l’ordre des numproduit

select numproduit
from produits
order by numproduit;

r8 : Affichez les numéros des produits qui ont été commandés

select distinct refproduit


from procom
order by refproduit;

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

select refmarque, nom


from produits
where refcateg = 3
order by refmarque desc, nom;

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%)

select nom, prix / 1.2 as HT


from produits
order by HT;

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

select nom, prix / 1.2 as HT, prix * 0.2/1.2 as TVA, prix


˓→as TTC

from produits
order by nom;

r14 : Afficher les départements des clients dans l’ordre croissant

select distinct substr(codepostal,1,2) as dpt


from clients
order by dpt;

r15 : Afficher les années des dates des commandes de la base

select distinct substr(date,1,4) as anneesCommandes


from commandes
order by anneesCommandes;

r16 : Affichez le nombre de produits dans la base.

select count(*) as nb from produits;

r17 : Affichez le maximum, le minimum et la moyenne des prix des produits.

select max(prix) as maxPrix, min(prix) as minPrix,


˓→avg(prix) as moyPrix

from produits;

r18 : Affichez le nombre d’articles vendus.

select sum(quantite) as nb
from procom;

r19 : Calculer le nombre de marques

select count(*) as nb
from marques;

r20 : Calculer le nombre de marques associées à des produits

select count(distinct refmarque) as nb


from produits;

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

-- ou avec l'autre syntaxe

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

Correction TD3 : Selections utilisant plusieurs tables

r1 : Affichez les noms des clients de Lille

select nom
from clients
where codepostal in
(select codepostal from villes
where ville = 'Lille');

r2 : Affichez les noms des clients de Lille et Roubaix

select nom
from clients
where codepostal in
(select codepostal from villes
where ville = 'Lille' or ville = 'Roubaix');

-- ou avec un IN pour la ville

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);

r4 : Afficher le nom du client qui a effectué la commande 1

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

select distinct nom


from clients
where numclient IN
(select refclient
from commandes
where date like '1997/01/%');

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);

r7 : Affichez la date des commandes effectuées par le client Alavie

select date
from commandes
where refclient =
(select numclient
from clients
where nom = 'Alavie');

r8 : Affichez la date de la première commande effectuée par le client Tabille

select min(date) as minDate


from commandes
where refclient =
(select numclient
from clients
where nom = 'Tabille');

r9 : Affichez le nombre d’articles achetés par le client de code 5 le jour de sa dernière


commande

select sum(quantite) as nbArticles


from procom
where refcommande IN
(select numcommande
from commandes
where date =

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

select distinct nom


from clients
where numclient in
(select refclient
from commandes
where date >=
(select min(date)
from commandes
where refclient =
(select numclient
from clients
where nom = 'Alavie'))
and date <=
(select max(date)
from commandes
where refclient =
(select numclient
from clients
where nom = 'Alavie'))
)
and nom != 'Alavie';

-- avec between

select distinct nom


from clients
where numclient in
(select refclient
from commandes
where date
between
(select min(date)
from commandes
where refclient =
(select numclient
from clients
where nom = 'Alavie'))
and
(select max(date)
from commandes
where refclient =
(select numclient
from clients

85
Bases de Données MIASHS, Version 1.0

where nom = 'Alavie'))


)
and nom != 'Alavie';

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

select nom, prenom


from clients
where numclient in
(select refclient
from commandes
where numcommande in
(select refcommande
from procom
where refproduit in
(select refproduit
from procom
where refcommande in
(select numcommande
from commandes
where refclient in
(select numclient
from clients
where nom = 'Alavie')))))
and nom != 'Alavie'
order by nom, prenom;

r13 : Affichez les nom et prénom des clients qui habitent la même ville que Peuleurido

select nom, prenom


from clients
where codepostal in
(select codepostal
from villes
where ville =
(select ville
from villes
where codepostal =
(select codepostal
from clients

86
Bases de Données MIASHS, Version 1.0

where nom = 'Peuleurido')))


and nom != 'Peuleurido';

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

select nom, prenom


from clients
where numclient in
(select refclient
from commandes
where numcommande in
(select refcommande
from procom
where refproduit in
(select numproduit
from produits
where prix > 1000)));

87
CHAPITRE 18

Correction TD4 : Jointures

r1 : Pour chaque produit, afficher sa marque et son nom dans l’ordre des marques puis
des produits

select marques.nom, produits.nom


from marques join produits on nummarque = refmarque
order by marques.nom, produits.nom;

r2 : Même question mais limitée aux produits de la catégorie Protection solaire

select marques.nom, produits.nom


from marques join produits on nummarque = refmarque
join categ on numcateg = refcateg
where categ.nom = 'Protection solaire'
order by marques.nom, produits.nom;

r3 : Affichez les noms des personnes de Lille en utilisant une jointure

select nom
from clients join villes on clients.codepostal = villes.
˓→codepostal

where ville = 'Lille';

r4 : Affichez les noms des produits qui ont été achetés en quantité > 2 pour au moins une
commande

select distinct nom


from produits join procom on numproduit = refproduit
where quantite > 2;

r5 : Afficher la quantité et le prix des produits de la commande 1

select quantite, prix


from procom join produits on numproduit = refproduit
where refcommande = 1;

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

select nom, quantite * prix as totalLigne


from procom join produits on numproduit = refproduit
where refcommande = 1;

r7 : Afficher le montant de la commande 1

select sum(quantite * prix) as totalCommande


from procom join produits on numproduit = refproduit
where refcommande = 1;

r8 : Affichez les noms et prénoms des clients qui habitent la même ville que Peuleurido
avec une autojointure

select C2.nom, C2.prenom


from clients C1 join villes V1 on C1.codepostal = V1.
˓→codepostal

join villes V2 on V1.ville = V2.ville


join clients C2 on C2.codepostal = V2.codepostal
where C1.nom = 'Peuleurido'
and C2.nom != 'Peuleurido'
order by C2.nom, C2.prenom;

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

select distinct C2.nom, C2.prenom


from clients C1 join commandes Comm1 on C1.numclient =
˓→Comm1.refclient

join procom Pro1 on Comm1.numcommande = Pro1.refcommande


join procom Pro2 on Pro1.refproduit = Pro2.refproduit
join commandes Comm2 on Comm2.numcommande = Pro2.
˓→refcommande

join clients C2 on C2.numclient = Comm2.refclient


where C1.nom = 'Alavie'
and C2.nom != 'Alavie'
order by C2.nom, C2.prenom;

r10 : Nom du client qui a acheté le produit le plus cher en janvier (de n’importe quelle
annee)

-- Avec la sous requete dans le join

select clients.nom, clients.prenom


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
join produits on numproduit = refproduit
join (select max(prix) as maxPrix from produits) on
˓→prix = maxPrix

where substr(date,6,2) = '01'; -- ou date like '%/01/%'

-- Avec la sous requete dans le where

89
Bases de Données MIASHS, Version 1.0

select clients.nom, clients.prenom


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
join produits on numproduit = refproduit
where substr(date,6,2) = '01'
and prix = (select max(prix) as maxPrix from produits);

r11 : Quels sont les clients qui ont acheté le produit le plus cher acheté par Pige

-- avec les conditions des sous requetes dans le where


select clients.nom
from procom join commandes on numcommande = refcommande
join clients on refclient = numclient,

(select numproduit, prix


from produits join procom on numproduit = refproduit
join commandes on numcommande = refcommande
join clients on numclient = refclient
where clients.nom = 'Pige')sr1,

(select max(prix) as maxprix from (select prix


from produits join procom on numproduit = refproduit
join commandes on numcommande = refcommande
join clients on numclient = refclient
where clients.nom = 'Pige')) sr2
where sr1.prix = sr2.maxprix
and sr1.numproduit = procom.refproduit
and clients.nom != 'Pige';

-- avec join pour les sous requetes


select clients.nom
from procom join commandes on numcommande = refcommande
join clients on refclient = numclient
join (select numproduit, prix
from produits join procom on numproduit = refproduit
join commandes on numcommande = refcommande
join clients on numclient = refclient
where clients.nom = 'Pige')sr1
on sr1.numproduit = procom.refproduit
join (select max(prix) as maxprix from (select prix
from produits join procom on numproduit = refproduit
join commandes on numcommande = refcommande
join clients on numclient = refclient
where clients.nom = 'Pige')) sr2
on sr1.prix = sr2.maxprix
where clients.nom != '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 produits.nom, quantite*prix as sansReduc,


case when quantite >= 3 then quantite*prix*0.1
else 0 end as Reduc,
case when quantite >= 3 then quantite*prix*0.9
else quantite*prix end as avecReduc
from procom join produits on numproduit = refproduit
where refcommande = 1;

r13 : Afficher le montant de la commande 1 en tenant compte de la réduction de la ques-


tion précédente

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é

select nom, prenom, minPrix


from clients left join (
select refclient, min(prix) as minPrix
from commandes join procom on numcommande = refcommande
join produits on numproduit = refproduit
group by refclient) sr1
on clients.numclient = sr1.refclient
where minPrix is null or minPrix >= 1000;

91
CHAPITRE 19

Correction TD5 : Regroupements

r1 : Affichez le nombre de produits par marque (sans la valeur 0)

select marques.nom, count(numproduit) as nbProduits


from marques join produits on nummarque = refmarque
group by marques.nom
order by marques.nom;

r2 : Affichez le nombre de produits par marque avec la valeur 0

select marques.nom, count(numproduit) as nbProduits


from marques left join produits on nummarque = refmarque
group by marques.nom
order by marques.nom;

r3 : Affichez le nombre de produits par catégorie

select categ.nom, count(numproduit) as nbProduits


from categ left join produits on numcateg = refcateg
group by categ.nom
order by categ.nom;

r4 : Affichez le nombre de produits vendus par catégorie

select categ.nom, sum(quantite) as nbProduits


from categ left join produits on numcateg = refcateg
left join procom on numproduit = refproduit
group by categ.nom
order by categ.nom;

r5 : Affichez le nombre de commandes par an

select substr(date,1,4) as annee, count(*) as nbCommandes


from commandes
group by annee
order by annee;

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

select clients.nom, clients.prenom


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
join produits on numproduit = refproduit
group by clients.nom, clients.prenom -- en toute rigueur
˓→numclient

having count(distinct refmarque) > 3;

r7 : Affichez le nombre de produits différents commandés par le client Alavie par com-
mande

select numcommande, count(refproduit) as nbProduits


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
where nom = 'Alavie'
group by numcommande;

r8 : Affichez le nombre d’articles commandés par le client Alavie par commande

select numcommande, sum(quantite) as nbArticles


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
where nom = 'Alavie'
group by numcommande;

r9 : Affichez le montant et la date des commandes effectuées par le client Tabille

select date, sum(quantite * prix) as montant


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
join produits on numproduit = refproduit
where clients.nom = 'Tabille'
group by date, numcommande;

r10 : Affichez le nom et prénom des clients dont le total des commandes est de plus de
5000 C

select clients.nom, clients.prenom


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
join produits on numproduit = refproduit
group by clients.nom, clients.prenom -- en toute rigueur
˓→numclient

having sum(quantite * prix) > 5000;

r11 : Affichez le nom et prénom des clients qui ont effectué au moins une commande de
plus de 5000 C

select distinct clients.nom, clients.prenom


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande

93
Bases de Données MIASHS, Version 1.0

join produits on numproduit = refproduit


group by numcommande, clients.nom, clients.prenom
having sum(quantite * prix) > 5000;

r12 : Affichez le montant de la plus grande commande

select max(montant) as maxMontant


from (select sum(quantite * prix) as montant
from procom join produits on numproduit = refproduit
group by refcommande);

r13 : Affichez les noms et prénoms des clients qui ont achetés plus que Tabille (au total)

-- Avec un having

select clients.nom, clients.prenom


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
join produits on numproduit = refproduit
group by clients.nom, clients.prenom
having sum(quantite*prix) >
(select sum(quantite*prix)
from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
join produits on numproduit = refproduit
where clients.nom = 'Tabille');

-- Avec deux sous-requetes

select nom, prenom


from
(select refclient, sum(quantite*prix) as montant
from commandes join procom on numcommande = refcommande
join produits on numproduit = refproduit
group by refclient) sr1,
(select sum(quantite*prix) as montant
from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
join produits on numproduit = refproduit
where clients.nom = 'Tabille') sr2,
clients
where sr1.montant > sr2.montant
and clients.numclient = sr1.refclient;

r14 : Affichez le nom et prénom du client qui a effectué la plus grande commande

-- Avec un having

select distinct clients.nom, clients.prenom


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande

94
Bases de Données MIASHS, Version 1.0

join produits on numproduit = refproduit


group by numcommande, clients.nom, clients.prenom
having sum(quantite * prix) =
(select max(montant)
from (select sum(quantite * prix) as montant
from procom join produits on numproduit = refproduit
group by refcommande));

-- Avec deux sous-requetes

select distinct clients.nom, clients.prenom


from
clients,
(select refclient, sum(quantite * prix) as montant
from commandes
join procom on numcommande = refcommande
join produits on numproduit = refproduit
group by numcommande, refclient) sr1,
(select max(montant) as maxMontant
from (select sum(quantite * prix) as montant
from procom join produits on numproduit = refproduit
group by refcommande)) sr2
where sr1.montant = sr2.maxMontant
and numclient = sr1.refclient;

r15 : Affichez le total des montants des commandes par an

select substr(date,1,4) as annee, sum(quantite * prix) as


˓→montant

from commandes join procom on numcommande = refcommande


join produits on numproduit = refproduit
group by annee;

r16 : Affichez l’année pour laquelle le total des montants des commandes est le plus faible

select annee from


(select substr(date,1,4) as annee, sum(quantite * prix)
˓→as montant

from commandes join procom on numcommande = refcommande


join produits on numproduit = refproduit
group by annee) sr1
where montant =
(select min(montant) from
(select sum(quantite * prix) as montant
from commandes join procom on numcommande = refcommande
join produits on numproduit = refproduit
group by substr(date,1,4)));

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

select nom, max(montant) as maxMontant


from (select clients.nom as nom, sum(quantite * prix) as
˓→montant

from clients join commandes on numclient = refclient


join procom on numcommande = refcommande
join produits on numproduit = refproduit
group by clients.nom, numcommande) sr1
group by nom
order by maxMontant desc;

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

select clients.nom, clients.prenom


from clients join commandes on numclient = refclient
join procom on numcommande = refcommande
join produits on numproduit = refproduit
where date like '1996/08/%'
group by numcommande, clients.nom, clients.prenom
having sum(quantite * prix) >=
(select max(montant) from
(select sum(quantite * prix) as montant
from commandes join procom on numcommande = refcommande
join produits on numproduit = refproduit
where date like '1996/01/%'
group by numcommande));

96
CHAPITRE 20

Correction TD6 : Synthèse

r1 : Affichez le nom et prénom des clients qui ont effectué une commande supérieure à la
moyenne des commandes

SELECT DISTINCT clients.nom, clients.prenom


FROM clients
JOIN commandes ON numclient = refclient
JOIN procom ON numcommande = refcommande
JOIN produits ON numproduit = refproduit,
-- sr1 : moyenne
(SELECT avg(montant) AS moyCommandes
FROM (SELECT Sum(quantite * prix) AS montant
FROM procom JOIN produits ON numproduit =
˓→refproduit

GROUP BY refcommande)) sr1


GROUP BY numcommande, clients.nom, clients.prenom
HAVING sum(quantite * prix) > moyCommandes;

r2 : Affichez le nom de la ville d’ou provient le plus grande nombre de 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

JOIN commandes ON numclient = refclient


GROUP BY Ville) ) sr2

97
Bases de Données MIASHS, Version 1.0

-- ville pour lesquelles le nb de commandes est egal au


˓→max
WHERE sr1.nbCommandes = sr2.maxNbCommandes;

r3 : Affichez le nom des villes qui font moins que 5% du nombre de commande

SELECT sr1.Ville, sr1.nbCommandes


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,
-- nombre de commandes
(SELECT Count(numcommande) AS nbCommandes
FROM commandes) sr2
-- nb de commndes < 5%
WHERE sr1.nbCommandes < sr2.nbCommandes * 0.05;

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,

(SELECT Max(nbMarques) AS maxNbMarques


FROM (SELECT Count(refmarque) AS nbMarques
FROM produits
JOIN procom ON numproduit = refproduit
GROUP BY refmarque) ) sr2

WHERE marques.nummarque = sr1.refmarque


AND sr1.nbMarques = sr2.maxNbMarques ;

r5 : Par catégorie, afficher le nom de la marque préférée

SELECT categ.nom, marques.nom


FROM categ, marques,
(SELECT refcateg, refmarque, Count(refproduit) AS
˓→nbProduits

FROM produits
JOIN procom ON numproduit = refproduit
GROUP BY refcateg, refmarque) sr1,

98
Bases de Données MIASHS, Version 1.0

(SELECT refcateg, Max(nbProduits) AS maxNbProduits


FROM (SELECT refcateg, Count(refproduit) AS nbProduits
FROM produits
JOIN procom ON numproduit = refproduit
GROUP BY refcateg, refmarque)
GROUP BY refcateg) sr2

WHERE sr1.nbProduits = sr2.maxNbProduits


AND sr1.refcateg = sr2.refcateg
AND sr1.refcateg = numcateg
AND sr1.refmarque = nummarque;

r6 : Affichez le classement des produits suivant les quantités demandées dans l’ordre
decroissant, les produits invendus devront apparaitre

SELECT Sum(quantite) AS total, nom


FROM produits
LEFT JOIN procom ON numproduit = refproduit
GROUP BY nom
ORDER BY Sum(quantite) DESC;

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,

(SELECT Avg(nbCommandes) AS moyNbCommandes --8b


FROM (SELECT Count(numcommande) AS nbCommandes
FROM commandes
GROUP BY refclient)) sr2

WHERE numclient = sr1.refclient


AND (sr1.nbCommandes >= sr2.moyNbCommandes * 0.7)
AND (sr1.nbCommandes <= sr2.moyNbCommandes * 1.3);

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

GROUP BY refclient, numcommande)


GROUP BY refclient) sr1,

(SELECT Avg(montant) AS moyMontant --9b


FROM (SELECT Sum(quantite * Prix) AS montant
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY refclient, numcommande)) sr2

WHERE sr1.moyMontant >= sr2.moyMontant * 0.7


AND sr1.moyMontant <= sr2.moyMontant * 1.3) sr1
WHERE numclient = sr1.refclient;

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

JOIN procom ON numcommande =


˓→refcommande

GROUP BY refclient, numcommande)


GROUP BY refclient) sr1,

(SELECT Avg(montant) AS moyMontant


FROM (SELECT Sum(quantite * Prix) AS montant
FROM produits
JOIN commandes ON numproduit =
˓→ refproduit
JOIN procom ON numcommande =
˓→ refcommande
GROUP BY refclient, numcommande)) sr2

WHERE sr1.moyMontant >= sr2.moyMontant * 0.7


AND sr1.moyMontant <= sr2.moyMontant * 1.
˓→ 3) sr1,

(SELECT sr1.refclient as refclient


FROM
(SELECT refclient, Count(numcommande) AS
˓→nbCommandes

FROM commandes
GROUP BY refclient) sr1,

100
Bases de Données MIASHS, Version 1.0

(SELECT Avg(nbCommandes) AS moyNbCommandes


FROM (SELECT Count(numcommande) AS nbCommandes
FROM commandes
GROUP BY refclient)) sr2

WHERE sr1.nbCommandes >= sr2.moyNbCommandes * 0.7


AND sr1.nbCommandes <= sr2.moyNbCommandes * 1.
3) sr2
˓→

WHERE sr1.refclient = sr2.refclient) sr1


----------------
WHERE numclient = sr1.refclient;

r10 : Affichez les noms des clients et le panier moyen des clients de profil type

SELECT nom, moyPanier


FROM clients,
(SELECT sr1.refclient as refclient, sr1.moyMontant as
˓→moyPanier

FROM (SELECT refclient, Avg(montant) AS moyMontant


FROM (SELECT refclient, numcommande, Sum(quantite
˓→* Prix) AS montant

FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY refclient, numcommande)
GROUP BY refclient) sr1,

(SELECT Avg(montant) AS moyMontant


FROM (SELECT Sum(quantite * Prix) AS montant
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY refclient, numcommande)) sr2
WHERE sr1.moyMontant >= sr2.moyMontant * 0.7
AND sr1.moyMontant <= sr2.moyMontant * 1.3) sr1,

(SELECT sr1.refclient as refclient


FROM (SELECT refclient, Count(numcommande) AS
˓→nbCommandes

FROM commandes
GROUP BY refclient) sr1,

(SELECT Avg(nbCommandes) AS moyNbCommandes


FROM (SELECT Count(numcommande) AS nbCommandes
FROM commandes
GROUP BY refclient)) sr2
WHERE sr1.nbCommandes >= sr2.moyNbCommandes * 0.7
AND sr1.nbCommandes <= sr2.moyNbCommandes * 1.3)
˓→ sr2

101
Bases de Données MIASHS, Version 1.0

WHERE sr1.refclient = sr2.refclient


AND numclient = sr1.refclient;

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.

CREATE VIEW clientstype as


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

JOIN procom ON numcommande =


˓→refcommande

GROUP BY refclient, numcommande)


GROUP BY refclient) sr1,

(SELECT Avg(montant) AS moyMontant


FROM (SELECT Sum(quantite * Prix) AS montant
FROM produits
JOIN commandes ON numproduit =
˓→ refproduit
JOIN procom ON numcommande =
˓→ refcommande
GROUP BY refclient, numcommande)) sr2

WHERE sr1.moyMontant >= sr2.moyMontant * 0.7


AND sr1.moyMontant <= sr2.moyMontant * 1.
˓→ 3) sr1,

(SELECT sr1.refclient as refclient


FROM
(SELECT refclient, Count(numcommande) AS
˓→nbCommandes

FROM commandes
GROUP BY refclient) sr1,

(SELECT Avg(nbCommandes) AS moyNbCommandes


FROM (SELECT Count(numcommande) AS nbCommandes
FROM commandes
GROUP BY refclient)) sr2

WHERE sr1.nbCommandes >= sr2.moyNbCommandes * 0.7


AND sr1.nbCommandes <= sr2.moyNbCommandes * 1.
3) sr2
˓→

WHERE sr1.refclient = sr2.refclient;

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

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;

r14 : Affichez par an le montant de l’évolution des paniers de profil type par rapport à
l’année précédente.

SELECT sr2.annee, (sr2.montantTotal - sr1.montantTotal) as


˓→evolution

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,

(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

103
Bases de Données MIASHS, Version 1.0

AND sr1.refclient = clientstype.refclient


GROUP BY annee) sr2
WHERE CAST(sr2.annee as integer) = CAST(sr1.annee as
˓→integer) + 1;

r15 : Affichez par an la difference entre le montant attendu des paniers de profil type et
le montant réalisé

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
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,

(SELECT substr(date,1,4) AS annee, Sum(quantite*Prix) AS


˓→montant

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.

SELECT sr1.annee, (sr2.difference - sr1.difference) as


˓→evolution

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

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,

(SELECT substr(date,1,4) AS annee, Sum(quantite*Prix)


˓→AS montant
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY annee) sr2
WHERE sr1.annee = sr2.annee) sr1,

(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
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,

(SELECT substr(date,1,4) AS annee, Sum(quantite*Prix)


˓→AS montant
FROM produits
JOIN commandes ON numproduit = refproduit
JOIN procom ON numcommande = refcommande
GROUP BY annee) sr2
WHERE sr1.annee = sr2.annee) sr2

WHERE CAST(sr2.annee as integer) = CAST(sr1.annee as


˓→integer) + 1;

105
CHAPITRE 21

Correction Cinema1

r1 : Afficher les noms des cinémas dans l’ordre alphabétique

select cinema.nomcine
from cinema
order by cinema.nomcine;

r2 : Titre, année de sortie et réalisateur des films français

select film.titre, film.annee, film.realisateur


from film
where film.pays = 'France';

r3 : Titres des films avec leur réalisateur, dans l’ordre alphabétique des titres de film

select film.titre, film.realisateur


from film
order by film.titre;

r4 : Nom des réalisateurs qui commencent par un T

select distinct film.realisateur


from film
where film.realisateur like 'T%';

r5 : Noms et numéros des acteurs du film “Cop”

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

select distinct film.annee


from film, distribution, acteurs
where film.idfilm = distribution.reffilm and

106
Bases de Données MIASHS, Version 1.0

distribution.refacteur = acteurs.idacteur and


acteurs.nomacteur = 'Gabin'
order by film.annee;

r7 : Films à l’affiche de la quatrième semaine dans chaque salle du cinéma gaumont

SELECT programme.salle, film.titre


FROM programme, film, cinema
WHERE film.idfilm = programme.reffilm and
cinema.idcine = programme.refcine and
programme.semaine = 4 and
cinema.nomcine = 'gaumont';

r8 : Acteurs qui ont tourné avec Truffaut comme réalisateur

SELECT DISTINCT acteurs.idacteur, acteurs.nomacteur


FROM acteurs, film, distribution
WHERE distribution.reffilm = film.idfilm and
distribution.refacteur = acteurs.idacteur and
film.realisateur = 'Truffaut';

r9 : Adresses des cinémas où passe un film réalisé par Crichton

SELECT DISTINCT cinema.nomcine, cinema.rue


FROM cinema, film, programme
WHERE programme.reffilm = film.idfilm and
programme.refcine = cinema.idcine and
film.realisateur = 'Crichton';

r10 : Rues, salles et nombres de places des cinémas où sont joués des films sortis en 1984
et dans lesquels joue Delon

SELECT DISTINCT cinema.rue, cinesalles.salle, cinesalles.


˓→nbplaces

FROM cinesalles, cinema, programme, film, distribution,


˓→acteurs

WHERE cinesalles.refcine = cinema.idcine and


cinesalles.refcine = programme.refcine and
cinesalles.salle = programme.salle and
programme.reffilm = film.idfilm and
programme.reffilm = distribution.reffilm and
acteurs.idacteur = distribution.refacteur and
acteurs.nomacteur = 'Delon' and
film.annee = 1984;

r11 : Titres et semaines de programmation des films dans lesquels jouent Deneuve ou
Eastwood

SELECT DISTINCT film.titre, programme.semaine


FROM programme, distribution, film, acteurs
WHERE programme.reffilm = film.idfilm AND

107
Bases de Données MIASHS, Version 1.0

distribution.reffilm = film.idfilm AND


acteurs.idacteur = distribution.refacteur AND
(acteurs.nomacteur = 'Eastwood' OR acteurs.nomacteur
˓→= 'Deneuve')

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.

SELECT DISTINCT film.realisateur, acteurs.nomacteur


FROM film, distribution, acteurs
WHERE film.idfilm = distribution.reffilm AND
acteurs.idacteur = distribution.refacteur AND
film.annee = 1989
ORDER BY film.realisateur, acteurs.nomacteur DESC;

108
CHAPITRE 22

Correction Cinema2

r1 : nb de films par acteur

select acteurs.nomacteur, count(distribution.reffilm) as


˓→nbFilms

from acteurs, distribution


where acteurs.idacteur = distribution.refacteur
group by acteurs.nomacteur;

r2 : Afficher pour le réalisateur Mieville, le nombre de films, en nommant nbreFilms le


titre de la colonne.

SELECT COUNT(idfilm) as nbreFilms


FROM film
WHERE realisateur = 'Mieville';

r3 : Afficher pour chaque réalisateur, le nombre de films, en commençant par celui qui a
réalisé le plus de films.

SELECT realisateur, COUNT(idfilm) as nbFilms


FROM film
GROUP BY realisateur
ORDER BY nbFilms DESC;

r4 : Afficher pour chaque réalisateur, le nombre de films, pour les réalisateurs qui ont fait
plus d’un film.

SELECT film.realisateur, COUNT(film.idfilm) as nbFilms


FROM film
GROUP BY film.realisateur
HAVING nbFilms > 1;

r5 : Nombre de semaines de programmation de chaque film.

SELECT titre, COUNT(DISTINCT semaine) as nbSemaines


FROM film, programme
WHERE reffilm = idfilm
GROUP BY titre;

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.

SELECT film.titre, COUNT(DISTINCT programme.refcine) as


˓→nbCinemas

FROM programme, film


WHERE film.idfilm = programme.reffilm
AND programme.semaine = 4
GROUP BY film.titre
HAVING nbCinemas >= 4
ORDER BY nbCinemas desc;

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')

and 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).

SELECT titre, realisateur, SUM(nbentrees) as nbTotalEntrees


FROM film, programme
WHERE semaine = 4
AND reffilm = idfilm
GROUP BY titre, realisateur
ORDER BY nbTotalEntrees DESC;

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';

r10 : Avec une aujointure Acteurs partenaires de Deneuve

SELECT DISTINCT a2.nomacteur


FROM acteurs a1, distribution d1, distribution d2, acteurs
˓→a2

WHERE a1.idacteur = d1.refacteur and


d1.reffilm = d2.reffilm and
d2.refacteur = a2.idacteur and
a1.nomacteur = 'Deneuve' and
a2.nomacteur <> 'Deneuve';

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

select acteurs.nomacteur, count(distinct d2.refacteur) -1


˓→as nbPartenaires

from acteurs, distribution d1, distribution d2


where acteurs.idacteur = d1.refacteur
and d1.reffilm = d2.reffilm
group by acteurs.nomacteur
order by nbPartenaires desc;

r13 : Avec une sous requete Acteurs partenaires de Deneuve

select distinct nomacteur


from acteurs, distribution
where idacteur = refacteur
and reffilm in -- attention!!! in different de egal
(select reffilm
from acteurs, distribution
where idacteur = refacteur
and nomacteur = 'Deneuve')
and nomacteur <> 'Deneuve';

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.

SELECT nomacteur, COUNT(DISTINCT d2.refacteur) - 1 as


˓→partenaires

FROM acteurs, distribution d1, distribution d2


WHERE idacteur = d1.refacteur AND
d1.reffilm = d2.reffilm
GROUP BY idacteur, nomacteur
ORDER BY COUNT(DISTINCT d2.refacteur) DESC;

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.

SELECT DISTINCT f1.titre, f1.annee, f1.pays


FROM film f1, film f2
WHERE f1.annee = f2.annee AND
f1.pays = f2.pays AND
f1.idfilm <> f2.idfilm
ORDER BY f1.annee, f1.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.

SELECT c1.nomcine, COUNT(DISTINCT p1.reffilm) AS Communs,


˓→c2.nomcine

FROM programme p1, programme p2, cinema c1, cinema c2


WHERE p1.refcine = c1.idcine AND
p2.refcine = c2.idcine AND
p1.semaine = p2.semaine AND
p1.reffilm = p2.reffilm
GROUP BY c1.nomcine, c2.nomcine
ORDER BY c1.nomcine, communs DESC, c2.nomcine;

r17 : Noms des cinémas ayant programmé un même film dans des salles différentes.

SELECT DISTINCT idcine, nomcine


FROM programme, cinema
WHERE refcine = idcine
GROUP BY idcine, nomcine, reffilm
HAVING COUNT(DISTINCT salle) > 1;

r18 : Pour chaque pays, donnez le nombre moyen d’acteurs par film.

SELECT pays, COUNT(refacteur)/COUNT(DISTINCT idfilm) as x


FROM distribution, film
WHERE idfilm = reffilm
GROUP BY pays
ORDER BY x;

r19 : Pour chaque année, noms des cinémas ayant eu à l’affiche tous les films sortis cette
année.

SELECT sr1.annee, nomcine


FROM (SELECT annee, refcine, COUNT(DISTINCT programme.
˓→reffilm) AS c

FROM programme, film


WHERE reffilm = idfilm
GROUP BY annee, refcine) sr1,
(SELECT annee, COUNT(titre) AS c
FROM film
GROUP BY annee) sr2,
cinema
WHERE sr1.annee = sr2.annee AND
sr1.c = sr2.c AND
sr1.refcine = cinema.idcine
ORDER BY sr1.annee;

112
CHAPITRE 23

Correction Cinema3

r1 : films qui ont au moins 6 acteurs

select reffilm , count(refacteur) from distribution


group by reffilm
having count(refacteur) >= 6;

r2 : nombre de films par decennie

select (annee-1900)/10*10 as decennie, count(idfilm) as


˓→nbFilms

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 nomacteur, 200000 + sum(nbentrees*0.5) as salaire


from acteurs, distribution, programme
where idacteur = refacteur
and distribution.reffilm = programme.reffilm
group by nomacteur;

r4 : pourcentage de remplissage des salles du cinema gaumont la semaine 4

select programme.salle, (nbentrees*100)/(7* nbplaces) as


˓→pourcentage

from programme, cinesalles, cinema


where programme.refcine = cinesalles.refcine
and programme.salle = cinesalles.salle
and programme.refcine = idcine
and semaine = 4
and nomcine = 'gaumont';

r5 : films qui n’ont pas ete programmes

select titre
from film left join programme on reffilm = idfilm
where reffilm is null;

113
Bases de Données MIASHS, Version 1.0

r6 : cinema qui n’ont rien programme la semaine 4

select nomcine
from cinema left join
(select refcine from programme where semaine = 4)
on idcine = refcine
where refcine is null;

r7 : film qui a fait le plus grand nombre d’entrees

select titre from


film,
(select reffilm, sum(nbentrees) as nbentrees
from programme group by reffilm) sr1 ,
(select max(nbentrees) as maxnbentrees from
(select sum(nbentrees) as nbentrees
from programme
group by reffilm)) sr2
where nbentrees = maxnbentrees
and reffilm = idfilm;

r8 : films dont le nombre d’entrees est superieur a la moyenne des entrees par semaine

select distinct titre


from programme, film,
(select semaine, avg(nbentrees) as moyenne from
(select semaine, sum(nbentrees) as nbentrees
from programme
group by semaine, reffilm )
group by semaine) sr1
where programme.semaine = sr1.semaine
and idfilm = reffilm
group by reffilm, programme.semaine
having sum(nbentrees) > moyenne ;

r9 : films dont le nombre d’entrées est égal à +/- 5 % de la moyenne des entrées par
semaine

select distinct titre


from programme, film,
(select semaine, avg(nbentrees) as moyenne from
(select semaine, sum(nbentrees) as nbentrees
from programme
group by semaine, reffilm )
group by semaine) sr1
where programme.semaine = sr1.semaine
and idfilm = reffilm
group by reffilm, programme.semaine
having sum(nbentrees) > moyenne * 0.95
and sum(nbentrees) < moyenne * 1.05;

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 ;

r12 : realisateur qui a fait le + grand nombre de films

select sr1.realisateur
from (select count(idfilm)as nb,realisateur from film
˓→group by realisateur) sr1,

(select max(nb) as nbMax


from (select count(idfilm) as nb from film group by
˓→realisateur))sr2

where sr1.nb = sr2.nbMax;

r13 : acteur le plus rentable (+ grand nombre d’entrées)

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;

r14 : realisateurs qui ne sont pas acteurs ss jointure gauche

select distinct realisateur


from film
where realisateur not in (select nomacteur from acteurs);

115
Bases de Données MIASHS, Version 1.0

r15 : realisateurs qui ne sont pas acteurs avec jointure gauche

select distinct realisateur


from film left join acteurs on realisateur = nomacteur
where nomacteur is null;

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

select nomcine, titre


from cinema, film,
(select p.refcine as refcine, reffilm, sum(nbplaces)
˓→as nbplaces

from cinesalles cs, programme p


where cs.refcine = p.refcine and semaine = 4
group by p.refcine, reffilm) sr1,
(select refcine, reffilm, sum(nbentrees) as nbentrees
from programme
where semaine = 4
group by reffilm, refcine) sr2
where sr1.refcine = sr2.refcine and
sr1.reffilm = sr2.reffilm and
nbentrees >= nbplaces / 2 and
idcine = sr1.refcine and
idfilm = sr1.reffilm;

r17 : nb de films par première lettre (A :2) : substr(champ,debut,nb)

select initiale, count(initiale) as nb from


(select substr(titre,1,1) as initiale from film)
group by initiale;

r18 : realisateur qui a tourné avec le plus grand nombre d’acteurs

select realisateur from


(select realisateur, count(distinct refacteur) as nb
from film,distribution
where idfilm = reffilm
group by realisateur) sr1,
(select max(nb) as maxnb from
(select count(distinct refacteur) as nb
from film,distribution
where idfilm = reffilm
group by realisateur))sr2
where nb = maxnb;

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'

when (nbentrees*100)/(7* nbplaces) > 80 then 'ouvrir'


else 'continuer' end) as action
from programme p, cinesalles cs, cinema,film
where p.refcine = cs.refcine
and p.salle = cs.salle
and cs.refcine = idcine
and idfilm = reffilm
and nomcine = 'le club'
and semaine = 4
group by p.salle,reffilm;

r22 : par cinema et par semaine, liste des salles sans programmation

select nomcine, cs.salle


from cinema,cinesalles cs left join
(select refcine, salle from programme where semaine =
˓→4) sr1

on cs.refcine = sr1.refcine and cs.salle = sr1.salle


where idcine = cs.refcine and
sr1.refcine is null;

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

select distinct nomacteur


from acteurs, distribution, film
where idfilm = reffilm
and idacteur = refacteur
and pays = 'Espagne'
and idacteur not in (
select refacteur from distribution, film
where idfilm = reffilm
and pays = 'USA');

118

Vous aimerez peut-être aussi