ajout de tous les cours et TP préparés cet été
This commit is contained in:
464
SQL/CORRIGE.md
Normal file
464
SQL/CORRIGE.md
Normal file
@@ -0,0 +1,464 @@
|
||||
# Corrigé des exercices — SQL
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1 : Requêtes SELECT simples
|
||||
|
||||
1. **Tous les livres de la table LIVRES.**
|
||||
```sql
|
||||
SELECT * FROM LIVRES;
|
||||
```
|
||||
|
||||
2. **Les titres et années de publication de tous les livres.**
|
||||
```sql
|
||||
SELECT titre, ann_publi FROM LIVRES;
|
||||
```
|
||||
|
||||
3. **Les noms et prénoms de tous les auteurs.**
|
||||
```sql
|
||||
SELECT nom, prenom FROM AUTEURS;
|
||||
```
|
||||
|
||||
4. **Les titres des livres publiés après 1950.**
|
||||
```sql
|
||||
SELECT titre FROM LIVRES WHERE ann_publi > 1950;
|
||||
```
|
||||
|
||||
5. **Les titres des livres du genre "dystopie".**
|
||||
```sql
|
||||
SELECT titre FROM LIVRES WHERE genre = 'dystopie';
|
||||
```
|
||||
|
||||
6. **Les auteurs de nationalité française.**
|
||||
```sql
|
||||
SELECT * FROM AUTEURS WHERE nationalite = 'français';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2 : Filtres et conditions
|
||||
|
||||
1. **Les livres publiés entre 1940 et 1960 (inclus).**
|
||||
```sql
|
||||
SELECT * FROM LIVRES WHERE ann_publi BETWEEN 1940 AND 1960;
|
||||
-- ou
|
||||
SELECT * FROM LIVRES WHERE ann_publi >= 1940 AND ann_publi <= 1960;
|
||||
```
|
||||
|
||||
2. **Les livres ayant plus de 300 pages.**
|
||||
```sql
|
||||
SELECT * FROM LIVRES WHERE nb_pages > 300;
|
||||
```
|
||||
|
||||
3. **Les auteurs nés après 1900 et de nationalité américaine.**
|
||||
```sql
|
||||
SELECT * FROM AUTEURS
|
||||
WHERE ann_naissance > 1900 AND nationalite = 'américain';
|
||||
```
|
||||
|
||||
4. **Les livres dont le titre contient le mot "Terre".**
|
||||
```sql
|
||||
SELECT * FROM LIVRES WHERE titre LIKE '%Terre%';
|
||||
```
|
||||
|
||||
5. **Les livres qui ne sont pas du genre "SF".**
|
||||
```sql
|
||||
SELECT * FROM LIVRES WHERE genre <> 'SF';
|
||||
-- ou
|
||||
SELECT * FROM LIVRES WHERE genre != 'SF';
|
||||
-- ou
|
||||
SELECT * FROM LIVRES WHERE NOT genre = 'SF';
|
||||
```
|
||||
|
||||
6. **Les auteurs dont le prénom commence par la lettre "R".**
|
||||
```sql
|
||||
SELECT * FROM AUTEURS WHERE prenom LIKE 'R%';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 : Tri et limitation
|
||||
|
||||
1. **Tous les livres triés par année de publication (du plus ancien au plus récent).**
|
||||
```sql
|
||||
SELECT * FROM LIVRES ORDER BY ann_publi ASC;
|
||||
-- ou simplement
|
||||
SELECT * FROM LIVRES ORDER BY ann_publi;
|
||||
```
|
||||
|
||||
2. **Les 5 livres les plus récents.**
|
||||
```sql
|
||||
SELECT * FROM LIVRES ORDER BY ann_publi DESC LIMIT 5;
|
||||
```
|
||||
|
||||
3. **Les auteurs triés par année de naissance décroissante.**
|
||||
```sql
|
||||
SELECT * FROM AUTEURS ORDER BY ann_naissance DESC;
|
||||
```
|
||||
|
||||
4. **Les 3 livres ayant le plus de pages.**
|
||||
```sql
|
||||
SELECT * FROM LIVRES ORDER BY nb_pages DESC LIMIT 3;
|
||||
```
|
||||
|
||||
5. **Les livres triés par genre, puis par titre alphabétique.**
|
||||
```sql
|
||||
SELECT * FROM LIVRES ORDER BY genre ASC, titre ASC;
|
||||
```
|
||||
|
||||
6. **La liste des genres sans doublons.**
|
||||
```sql
|
||||
SELECT DISTINCT genre FROM LIVRES;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 4 : Fonctions d'agrégation
|
||||
|
||||
1. **Le nombre total de livres dans la base.**
|
||||
```sql
|
||||
SELECT COUNT(*) FROM LIVRES;
|
||||
-- Résultat : 12
|
||||
```
|
||||
|
||||
2. **Le nombre de pages du livre le plus long.**
|
||||
```sql
|
||||
SELECT MAX(nb_pages) FROM LIVRES;
|
||||
-- Résultat : 896 (Dune)
|
||||
```
|
||||
|
||||
3. **L'année de publication du livre le plus ancien.**
|
||||
```sql
|
||||
SELECT MIN(ann_publi) FROM LIVRES;
|
||||
-- Résultat : 1865 (De la Terre à la Lune)
|
||||
```
|
||||
|
||||
4. **Le nombre moyen de pages des livres.**
|
||||
```sql
|
||||
SELECT AVG(nb_pages) FROM LIVRES;
|
||||
-- Résultat : environ 333.25
|
||||
```
|
||||
|
||||
5. **Le nombre de livres par genre.**
|
||||
```sql
|
||||
SELECT genre, COUNT(*) AS nb_livres
|
||||
FROM LIVRES
|
||||
GROUP BY genre;
|
||||
```
|
||||
Résultat :
|
||||
| genre | nb_livres |
|
||||
|-------|-----------|
|
||||
| aventure | 2 |
|
||||
| dystopie | 3 |
|
||||
| post-apo | 1 |
|
||||
| SF | 4 |
|
||||
| space opera | 2 |
|
||||
|
||||
6. **Le nombre total de pages de tous les livres de Jules Verne (id_auteur = 8).**
|
||||
```sql
|
||||
SELECT SUM(nb_pages) FROM LIVRES WHERE id_auteur = 8;
|
||||
-- Résultat : 672 (192 + 480)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 5 : GROUP BY et HAVING
|
||||
|
||||
1. **Le nombre de livres écrits par chaque auteur.**
|
||||
```sql
|
||||
SELECT id_auteur, COUNT(*) AS nb_livres
|
||||
FROM LIVRES
|
||||
GROUP BY id_auteur;
|
||||
```
|
||||
|
||||
2. **Le nombre moyen de pages par genre.**
|
||||
```sql
|
||||
SELECT genre, AVG(nb_pages) AS moy_pages
|
||||
FROM LIVRES
|
||||
GROUP BY genre;
|
||||
```
|
||||
|
||||
3. **Les genres ayant plus de 2 livres.**
|
||||
```sql
|
||||
SELECT genre, COUNT(*) AS nb_livres
|
||||
FROM LIVRES
|
||||
GROUP BY genre
|
||||
HAVING COUNT(*) > 2;
|
||||
```
|
||||
Résultat : dystopie (3), SF (4)
|
||||
|
||||
4. **Les auteurs ayant écrit au moins 2 livres.**
|
||||
```sql
|
||||
SELECT id_auteur, COUNT(*) AS nb_livres
|
||||
FROM LIVRES
|
||||
GROUP BY id_auteur
|
||||
HAVING COUNT(*) >= 2;
|
||||
```
|
||||
Résultat : id_auteur 3, 5, 7, 8 (Asimov, Bradbury, Barjavel, Verne)
|
||||
|
||||
5. **L'année de publication du premier livre de chaque auteur.**
|
||||
```sql
|
||||
SELECT id_auteur, MIN(ann_publi) AS premier_livre
|
||||
FROM LIVRES
|
||||
GROUP BY id_auteur;
|
||||
```
|
||||
|
||||
6. **Les genres dont la moyenne de pages dépasse 250.**
|
||||
```sql
|
||||
SELECT genre, AVG(nb_pages) AS moy_pages
|
||||
FROM LIVRES
|
||||
GROUP BY genre
|
||||
HAVING AVG(nb_pages) > 250;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 6 : Jointures
|
||||
|
||||
1. **Les titres des livres avec le nom et prénom de leur auteur.**
|
||||
```sql
|
||||
SELECT L.titre, A.nom, A.prenom
|
||||
FROM LIVRES L
|
||||
INNER JOIN AUTEURS A ON L.id_auteur = A.id;
|
||||
```
|
||||
|
||||
2. **Les titres des livres écrits par des auteurs français.**
|
||||
```sql
|
||||
SELECT L.titre
|
||||
FROM LIVRES L
|
||||
INNER JOIN AUTEURS A ON L.id_auteur = A.id
|
||||
WHERE A.nationalite = 'français';
|
||||
```
|
||||
Résultat : La nuit des temps, Ravage, De la Terre à la Lune, Vingt mille lieues sous les mers
|
||||
|
||||
3. **Les titres et auteurs des livres du genre "dystopie", triés par année.**
|
||||
```sql
|
||||
SELECT L.titre, A.nom, A.prenom, L.ann_publi
|
||||
FROM LIVRES L
|
||||
INNER JOIN AUTEURS A ON L.id_auteur = A.id
|
||||
WHERE L.genre = 'dystopie'
|
||||
ORDER BY L.ann_publi;
|
||||
```
|
||||
|
||||
4. **Le nom des auteurs ayant écrit des livres de plus de 400 pages.**
|
||||
```sql
|
||||
SELECT DISTINCT A.nom, A.prenom
|
||||
FROM AUTEURS A
|
||||
INNER JOIN LIVRES L ON A.id = L.id_auteur
|
||||
WHERE L.nb_pages > 400;
|
||||
```
|
||||
Résultat : Herbert Frank, Verne Jules
|
||||
|
||||
5. **Les livres avec le nom de l'auteur, pour les auteurs américains nés après 1910.**
|
||||
```sql
|
||||
SELECT L.titre, A.nom
|
||||
FROM LIVRES L
|
||||
INNER JOIN AUTEURS A ON L.id_auteur = A.id
|
||||
WHERE A.nationalite = 'américain' AND A.ann_naissance > 1910;
|
||||
```
|
||||
|
||||
6. **Pour chaque nationalité, le nombre de livres écrits.**
|
||||
```sql
|
||||
SELECT A.nationalite, COUNT(*) AS nb_livres
|
||||
FROM AUTEURS A
|
||||
INNER JOIN LIVRES L ON A.id = L.id_auteur
|
||||
GROUP BY A.nationalite;
|
||||
```
|
||||
Résultat :
|
||||
| nationalite | nb_livres |
|
||||
|-------------|-----------|
|
||||
| américain | 6 |
|
||||
| britannique | 2 |
|
||||
| français | 4 |
|
||||
|
||||
---
|
||||
|
||||
## Exercice 7 : Requêtes complexes
|
||||
|
||||
1. **Le titre du livre le plus long de chaque auteur, avec le nom de l'auteur.**
|
||||
```sql
|
||||
SELECT A.nom, A.prenom, L.titre, L.nb_pages
|
||||
FROM LIVRES L
|
||||
INNER JOIN AUTEURS A ON L.id_auteur = A.id
|
||||
WHERE L.nb_pages = (
|
||||
SELECT MAX(nb_pages)
|
||||
FROM LIVRES
|
||||
WHERE id_auteur = L.id_auteur
|
||||
);
|
||||
```
|
||||
|
||||
2. **Les auteurs n'ayant écrit qu'un seul livre.**
|
||||
```sql
|
||||
SELECT A.nom, A.prenom, L.titre
|
||||
FROM AUTEURS A
|
||||
INNER JOIN LIVRES L ON A.id = L.id_auteur
|
||||
WHERE A.id IN (
|
||||
SELECT id_auteur
|
||||
FROM LIVRES
|
||||
GROUP BY id_auteur
|
||||
HAVING COUNT(*) = 1
|
||||
);
|
||||
```
|
||||
|
||||
3. **Le nombre moyen de pages des livres par nationalité d'auteur.**
|
||||
```sql
|
||||
SELECT A.nationalite, AVG(L.nb_pages) AS moy_pages
|
||||
FROM AUTEURS A
|
||||
INNER JOIN LIVRES L ON A.id = L.id_auteur
|
||||
GROUP BY A.nationalite;
|
||||
```
|
||||
|
||||
4. **Les genres pour lesquels tous les livres ont été publiés après 1940.**
|
||||
```sql
|
||||
SELECT genre
|
||||
FROM LIVRES
|
||||
GROUP BY genre
|
||||
HAVING MIN(ann_publi) > 1940;
|
||||
```
|
||||
Résultat : dystopie (min 1931... non!), SF (min 1950), space opera (min 1951)
|
||||
|
||||
Note : En vérifiant les données, "Le meilleur des mondes" (dystopie) est de 1931, donc dystopie ne correspond pas. Les genres valides sont : SF, space opera, post-apo.
|
||||
|
||||
5. **Le nom complet des auteurs et le nombre total de pages qu'ils ont écrites.**
|
||||
```sql
|
||||
SELECT A.prenom || ' ' || A.nom AS nom_complet, SUM(L.nb_pages) AS total_pages
|
||||
FROM AUTEURS A
|
||||
INNER JOIN LIVRES L ON A.id = L.id_auteur
|
||||
GROUP BY A.id
|
||||
ORDER BY total_pages DESC;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 8 : INSERT, UPDATE, DELETE
|
||||
|
||||
1. **Ajouter l'auteur Ursula K. Le Guin.**
|
||||
```sql
|
||||
INSERT INTO AUTEURS (id, nom, prenom, nationalite, ann_naissance)
|
||||
VALUES (9, 'Le Guin', 'Ursula K.', 'américain', 1929);
|
||||
```
|
||||
|
||||
2. **Ajouter le livre "La Main gauche de la nuit".**
|
||||
```sql
|
||||
INSERT INTO LIVRES (id, titre, id_auteur, ann_publi, genre, nb_pages)
|
||||
VALUES (13, 'La Main gauche de la nuit', 9, 1969, 'SF', 304);
|
||||
```
|
||||
|
||||
3. **Changer le genre de "Dune" en "SF".**
|
||||
```sql
|
||||
UPDATE LIVRES
|
||||
SET genre = 'SF'
|
||||
WHERE titre = 'Dune';
|
||||
```
|
||||
|
||||
4. **Augmenter de 10% le nombre de pages de tous les livres de Jules Verne.**
|
||||
```sql
|
||||
UPDATE LIVRES
|
||||
SET nb_pages = nb_pages * 1.1
|
||||
WHERE id_auteur = 8;
|
||||
```
|
||||
|
||||
5. **Supprimer tous les livres publiés avant 1900.**
|
||||
```sql
|
||||
DELETE FROM LIVRES
|
||||
WHERE ann_publi < 1900;
|
||||
```
|
||||
Note : Cela supprimera "De la Terre à la Lune" (1865) et "Vingt mille lieues sous les mers" (1870).
|
||||
|
||||
---
|
||||
|
||||
## Exercice 9 : Création de tables
|
||||
|
||||
1. **Créer la table EMPRUNTS.**
|
||||
```sql
|
||||
CREATE TABLE EMPRUNTS (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id_livre INTEGER,
|
||||
id_adherent INTEGER,
|
||||
date_emprunt DATE,
|
||||
date_retour DATE,
|
||||
FOREIGN KEY (id_livre) REFERENCES LIVRES(id)
|
||||
);
|
||||
```
|
||||
|
||||
2. **Créer la table EDITEURS.**
|
||||
```sql
|
||||
CREATE TABLE EDITEURS (
|
||||
id INTEGER PRIMARY KEY,
|
||||
nom TEXT,
|
||||
pays TEXT,
|
||||
ann_creation INTEGER
|
||||
);
|
||||
```
|
||||
|
||||
3. **Ajouter une colonne id_editeur à la table LIVRES.**
|
||||
```sql
|
||||
ALTER TABLE LIVRES ADD COLUMN id_editeur INTEGER REFERENCES EDITEURS(id);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 10 : Analyse de requêtes
|
||||
|
||||
1. **Requête avec sous-requête MIN :**
|
||||
```sql
|
||||
SELECT titre FROM LIVRES WHERE ann_publi = (SELECT MIN(ann_publi) FROM LIVRES);
|
||||
```
|
||||
**Explication :** Cette requête retourne le titre du livre le plus ancien de la base. La sous-requête trouve l'année minimale, puis la requête principale sélectionne le(s) livre(s) publié(s) cette année-là.
|
||||
|
||||
**Résultat :** "De la Terre à la Lune" (1865)
|
||||
|
||||
2. **Requête complexe avec double sous-requête :**
|
||||
```sql
|
||||
SELECT A.nom, COUNT(*)
|
||||
FROM AUTEURS A
|
||||
INNER JOIN LIVRES L ON A.id = L.id_auteur
|
||||
GROUP BY A.id
|
||||
HAVING COUNT(*) = (SELECT MAX(cnt) FROM (SELECT COUNT(*) as cnt FROM LIVRES GROUP BY id_auteur));
|
||||
```
|
||||
**Explication :** Cette requête retourne le(s) auteur(s) ayant écrit le plus grand nombre de livres. La sous-requête interne compte les livres par auteur, la sous-requête externe trouve le maximum, et la requête principale affiche les auteurs atteignant ce maximum.
|
||||
|
||||
**Résultat :** Les auteurs avec 2 livres chacun (Asimov, Bradbury, Barjavel, Verne)
|
||||
|
||||
3. **Requête avec NOT IN :**
|
||||
```sql
|
||||
SELECT DISTINCT genre FROM LIVRES WHERE genre NOT IN (SELECT genre FROM LIVRES WHERE ann_publi < 1950);
|
||||
```
|
||||
**Explication :** Cette requête retourne les genres pour lesquels AUCUN livre n'a été publié avant 1950. La sous-requête trouve les genres ayant au moins un livre avant 1950, puis la requête principale exclut ces genres.
|
||||
|
||||
**Résultat :** Les genres dont tous les livres sont de 1950 ou après (SF, space opera, potentiellement post-apo selon les données)
|
||||
|
||||
---
|
||||
|
||||
## Exercice 11 : QCM
|
||||
|
||||
1. **Quelle clause permet de filtrer les résultats d'un GROUP BY ?**
|
||||
- **Réponse : c) HAVING**
|
||||
|
||||
2. **Quelle est la différence entre WHERE et HAVING ?**
|
||||
- **Réponse : b) WHERE filtre avant GROUP BY, HAVING filtre après**
|
||||
|
||||
Explication : WHERE filtre les lignes individuelles avant le regroupement. HAVING filtre les groupes après le regroupement et permet d'utiliser des fonctions d'agrégation.
|
||||
|
||||
3. **Que retourne `SELECT COUNT(*) FROM LIVRES WHERE 1=0;` ?**
|
||||
- **Réponse : c) 0**
|
||||
|
||||
Explication : La condition `1=0` est toujours fausse, donc aucune ligne n'est sélectionnée. COUNT(*) sur un ensemble vide retourne 0 (pas NULL, pas d'erreur).
|
||||
|
||||
4. **Quel type de jointure retourne tous les enregistrements de la table de gauche ?**
|
||||
- **Réponse : b) LEFT JOIN**
|
||||
|
||||
Explication : LEFT JOIN retourne toutes les lignes de la table de gauche, même si elles n'ont pas de correspondance dans la table de droite (avec NULL pour les colonnes de droite).
|
||||
|
||||
5. **Quelle fonction d'agrégation ignore les valeurs NULL ?**
|
||||
- **Réponse : b) COUNT(colonne)**
|
||||
|
||||
Explication : `COUNT(*)` compte toutes les lignes, y compris celles avec des NULL. `COUNT(colonne)` ne compte que les valeurs non NULL de cette colonne.
|
||||
|
||||
---
|
||||
|
||||
Auteur : Florian Mathieu
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
Reference in New Issue
Block a user