Files
TermNSI/SQL/CORRIGE.md

465 lines
12 KiB
Markdown

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