Exercices corrigés : modélisation, algèbre et SQL
Ce que ce chapitre apporte 6 points
- Construire un MCD puis un MLD à partir d'un énoncé en langage courant.
- Traduire une association N-M en table de liaison, et placer ses attributs au bon endroit.
- Écrire les requêtes de création, de modification et d'interrogation, et les faire juger sur plusieurs états de la base.
- Passer d'une requête SQL à une expression d'algèbre relationnelle, et inversement.
- Construire un arbre algébrique, en poussant les sélections au plus près des feuilles.
- Écrire des requêtes imbriquées : sous-requête scalaire, IN, EXISTS, et la négation qui résiste aux NULL.
Le module mis en pratique. Placés après tout le cours, ces trente exercices en reprennent la matière : la modélisation, le SQL, l'algèbre relationnelle et ses arbres, les requêtes imbriquées. Chaque partie nomme le chapitre où elle s'enseigne ; les transactions ont leurs exercices à la fin de leur chapitre.
Les requêtes et les expressions s'écrivent dans la page. « Exécuter » montre ce que la saisie rend ; « Vérifier » la juge sur plusieurs états de la base, ceux que décrit chaque libellé, et sur un cas caché dont seul le verdict s'affiche : il démasque une réponse écrite pour les seules données visibles. Les indices se dévoilent un à un, le dernier nomme le piège de l'exercice, et une correction s'ouvre après deux vérifications ou une réussite. Les modèles, et trois arbres que la machine ne sait pas juger, gardent un corrigé replié, précédé d'un cadre qui fait annoncer ce qu'il doit contenir.
- Annoncer le résultat avant d'écrire : ses colonnes, son nombre de lignes à peu près.
- Écrire, exécuter, comparer à l'annonce, puis vérifier. Un cas qui échoue dit ce qui diffère ; le cas caché dit seulement s'il passe.
- En cas de blocage, relire le chapitre de la partie, puis demander un indice, un seul à la fois.
- Une fois l'exercice réussi, ouvrir les indices restants : le dernier dit pourquoi la réponse fausse la plus courante semblait raisonnable.
Partie 1, Modélisation, du MCD au MLD
Ces exercices reprennent Du MCD au modèle relationnel. Pour chaque énoncé, identifier d'abord les entités, puis les associations entre elles et leurs cardinalités.
La faute de cette partie est presque toujours la même : ranger dans une entité un attribut qui appartient à l'association, ou traduire une association N-M par une clé étrangère au lieu d'une table. Les cinq corrigés reviennent dessus sous des habillages différents. Un modèle se discute plus qu'il ne se juge : les corrigés restent repliés, et un cadre de calcul fait d'abord compter ce que le MLD doit contenir.
Exercice 1, Bibliothèque
Une bibliothèque gère des livres, des auteurs et des emprunts.
- Un auteur peut avoir écrit plusieurs livres, et un livre a un seul auteur principal.
- Un lecteur peut emprunter plusieurs livres, et un livre peut être emprunté par plusieurs lecteurs (à des dates différentes).
- Pour chaque emprunt, la bibliothèque enregistre la date d'emprunt et la date de retour prévue.
- Identifier les entités et leurs attributs.
- Identifier les associations et leurs cardinalités.
- Proposer un MCD (notation textuelle).
- Déduire le MLD correspondant.
Ce que le MLD de la bibliothèque contient
- 1.
Combien de tables le MLD de la bibliothèque compte-t-il ?
- 2.
Combien de colonnes forment la clé primaire de la table des emprunts ?
- 3.
Combien de clés étrangères le MLD déclare-t-il en tout ?
Afficher la correction
Entités et attributs :
Auteur: idAuteur, nom, prenomLivre: idLivre, titre, genre, anneeLecteur: idLecteur, nom, prenom, email
Associations :
Auteur-(1,N)- Ecrit -(1,1)-Livre→ un auteur a écrit au moins un livre, un livre a exactement un auteur principalLecteur-(0,N)- Emprunt -(0,N)-Livre→ association N-M, à laquelle une troisième entité,Date, donne la date d'emprunt ; la date de retour est un attribut de l'association
MCD :
Rectangle : entité, identifiant souligné. Losange : association. Les couples min,max portés sur les pattes se lisent depuis l'entité la plus proche.
Une cardinalité décrit l'entité qu'elle touche : le (1,1) collé à Livre dit qu'un livre participe une seule fois à Ecrit, donc qu'il a un seul auteur. C'est ce (1,1), et lui seul, qui décide que la clé étrangère idAuteur se loge dans Livre. Les (0,N) autour d'Emprunt ne se logent nulle part : ils imposent une table, dont la clé réunit celles des trois entités reliées. L'entité Date ne devient pas une table pour autant : elle n'a pas d'autre attribut que sa clé, qui ne sert qu'à entrer dans celle de l'emprunt.
MLD :
clé primaire clé étrangère, avec la table visée
Le piège : s'arrêter à la clé (idLivre, idLecteur). C'est le réflexe normal, puisque c'est la forme habituelle d'une table de liaison. Mais elle interdit alors qu'un lecteur emprunte deux fois le même livre, ce que l'énoncé autorise expressément en parlant de dates différentes. La date fait partie de l'identité de l'emprunt : elle entre dans la clé primaire. Dans le MCD, cela se dit en reliant l'association à une troisième entité, Date : sa clé rejoint alors les deux autres dans la clé primaire de la table, par la règle ordinaire.
Le contrôle à faire à chaque table de liaison : inventer deux lignes que la réalité autorise, par exemple « le lecteur 3 emprunte le livre 7 en janvier, puis en mars ». Vérifier ensuite que la clé choisie les accepte toutes les deux.
L'exercice La date dans la clé, sur la page Exercices, pose le même problème et le corrige.
Exercice 2, Entreprise et projets
Une entreprise souhaite modéliser ses salariés, départements et projets.
- Chaque salarié appartient à un seul département.
- Un salarié peut travailler sur plusieurs projets.
- Un projet peut impliquer plusieurs salariés.
- L'entreprise veut aussi connaître le rôle de chaque salarié sur un projet (par exemple développeur, chef de projet).
- Proposer le MCD.
- Déduire le MLD.
- Quelle est la nature de l'association Salarié-Projet ? Comment se traduit-elle en MLD ?
Ce que le MLD de l'entreprise contient
- 1.
Combien de tables le MLD compte-t-il ?
- 2.
Combien de colonnes compte la table née de l'association entre salariés et projets ?
Afficher la correction
MCD :
Rectangle : entité, identifiant souligné. Losange : association. Les couples min,max portés sur les pattes se lisent depuis l'entité la plus proche.
MLD :
clé primaire clé étrangère, avec la table visée
Explication :
- L'association Département-Salarié est 1-N : elle se traduit par une clé étrangère
idDeptdans la tableSalarie. - L'association Salarié-Projet est N-M : elle génère une table de liaison
TravailleSur. - L'attribut
roleappartient à l'association (pas à une entité) : il va dans la table de liaison.
Le piège : placer role dans Salarie. L'erreur est naturelle, parce que la phrase de l'énoncé dit « le rôle de chaque salarié » et semble donc décrire le salarié. Le test qui tranche : un même salarié peut-il avoir deux rôles en même temps ? Oui, un par projet. Un attribut qui change selon le projet ne peut pas être rangé dans le salarié.
Exercice 3, Plateforme vidéo
Modéliser une plateforme de vidéos en ligne avec les règles suivantes :
- Un utilisateur peut poster plusieurs vidéos.
- Un utilisateur peut commenter plusieurs vidéos.
- Chaque commentaire est lié à une vidéo et à un utilisateur.
- Une vidéo peut recevoir plusieurs commentaires.
- La plateforme veut aussi enregistrer les likes (un utilisateur peut liker plusieurs vidéos).
- Proposer le MCD.
- Déduire le MLD.
Ce que le MLD de la plateforme contient
- 1.
Combien de tables le MLD compte-t-il ?
- 2.
Combien de clés étrangères la table des commentaires porte-t-elle ?
- 3.
Combien de clés étrangères le MLD déclare-t-il en tout ?
Afficher la correction
MCD :
Rectangle : entité, identifiant souligné. Losange : association. Les couples min,max portés sur les pattes se lisent depuis l'entité la plus proche.
Utilisateur revient sur les trois lignes, et c'est ce qu'il faut regarder : la même entité y tient trois rôles sans rapport entre eux. Chacun se traduira séparément, et deux d'entre eux seulement donneront une clé étrangère. Le Commentaire porte deux (1,1) : c'est lui qui recevra les deux clés étrangères, vers son auteur et vers sa vidéo.
MLD :
clé primaire clé étrangère, avec la table visée
Explication :
Videoporte la cléidUsercar un utilisateur poste une vidéo (association 1-N).Commentaireporte deux clés étrangères : vers l'auteur du commentaire et vers la vidéo concernée.Likeest une table de liaison N-M entreUtilisateuretVideo.
Le piège : traiter Commentaire et Like de la même façon, puisque les deux relient un utilisateur à une vidéo. Un like n'a pas d'existence propre : deux likes identiques sont le même like, donc une table de liaison suffit. Un commentaire a un contenu, une date, une identité : deux commentaires identiques restent deux commentaires. C'est une entité.
Exercice 4, Hôtel
Un hôtel souhaite gérer ses chambres, ses clients et ses réservations.
- Un client peut effectuer plusieurs réservations.
- Une réservation porte sur une seule chambre.
- Une chambre a un type (simple, double, suite) et un tarif par nuit.
- L'hôtel enregistre pour chaque réservation la date d'arrivée et la date de départ.
- Identifier les entités et leurs attributs.
- Identifier les associations et leurs cardinalités.
- Proposer le MLD.
Ce que le MLD de l'hôtel contient
- 1.
Combien de tables le MLD compte-t-il ?
- 2.
Combien de clés étrangères la table des réservations porte-t-elle ?
- 3.
Combien de colonnes forment sa clé primaire ?
Afficher la correction
Entités et attributs :
Client: idClient, nom, prenom, email, telephoneChambre: idChambre, numero, type, tarifNuitReservation: idReservation, dateArrivee, dateDepart
Associations :
Client-(1,N)- Effectue -(1,1)-Reservation→ un client peut avoir plusieurs réservations, une réservation appartient à un seul clientChambre-(0,N)- Concerne -(1,1)-Reservation→ une chambre peut être réservée plusieurs fois (à des dates différentes), une réservation porte sur une chambre
MLD :
clé primaire clé étrangère, avec la table visée
Le piège : voir une association N-M entre Client et Chambre et fabriquer une table de liaison Client-Chambre. L'erreur est naturelle, car la forme est la même : deux clés étrangères et des attributs. Ce qui la départage, c'est qu'une réservation s'annule, se modifie, se numérote et se communique au client. Un objet dont l'entreprise parle au quotidien est une entité, pas un lien.
Ce que la clé n'empêche pas : deux réservations de la même chambre sur des dates qui se chevauchent. La clé primaire ne regarde que l'identifiant de la réservation ; ce contrôle-là se fait par une requête avant l'insertion, ou par un déclencheur.
Exercice 5, Réseau social
Un réseau social permet à des utilisateurs de se suivre mutuellement et de publier des posts.
- Un utilisateur peut suivre plusieurs autres utilisateurs (un abonnement).
- Un utilisateur peut publier plusieurs posts.
- Un post peut recevoir des likes d'autres utilisateurs.
- Le réseau veut savoir qui suit qui et depuis quand.
- Identifier les entités et les associations (attention : l'association « suit » est réflexive).
- Proposer le MLD.
Afficher la correction
Entités :
Utilisateur: idUser, pseudo, email, dateInscriptionPost: idPost, contenu, datePublication
Associations :
- Suit :
Utilisateur-(0,N)- suit -(0,N)-Utilisateur→ association réflexive N-M (un utilisateur peut en suivre plusieurs, et être suivi par plusieurs) - Publier :
Utilisateur-(0,N)- publie -(1,1)-Post→ association 1-N - Like :
Utilisateur-(0,N)- like -(0,N)-Post→ association N-M
MLD :
clé primaire clé étrangère, avec la table visée
Point clé, l'association réflexive : la table Abonnement référence deux fois Utilisateur avec deux noms différents (idSuiveur = celui qui suit, idSuivi = celui qui est suivi). Les deux colonnes pointent vers la même table mais ont des rôles distincts. Rien n'empêche encore un utilisateur de se suivre lui-même : une contrainte CHECK (idSuiveur <> idSuivi) l'interdit.
Le piège : nommer les deux colonnes idUser1 et idUser2. Rien ne l'interdit, et au moment où la table est écrite le sens paraît évident. Il ne l'est plus à la première requête : « les abonnés de Marie » et « les comptes que Marie suit » deviennent indiscernables. Dans une association réflexive, le nom de la colonne est la seule trace du rôle.
Partie 2, Créer, modifier et interroger en SQL
La modélisation étant faite, la suite l'exécute : les mêmes entités deviennent des tables, puis des résultats. Ces exercices reprennent Les requêtes SQL et, pour les comptes et les moyennes des exercices 8 et 9, le début de SQL avancé.
Chaque vérification part de la base du module, celle des chapitres sur l'algèbre et sur le SQL, puis la modifie comme le dit son libellé : un étudiant de plus, une note changée, un cours qui ouvre. Le bouton du schéma, en tête de l'éditeur, en montre les tables. Quand l'énoncé demande un ordre, l'ordre des lignes compte ; sinon, il est libre.
Schéma de référence :
clé primaire clé étrangère, avec la table visée
Ce que la base contient : dix étudiants, sept cours, vingt-cinq inscriptions dont deux sans note. Une requête sur les inscriptions qui rend plus de vingt-cinq lignes a dupliqué quelque chose ; une requête qui en rend moins a filtré quelque chose, volontairement ou non.
Exercice 6, Mise en place du schéma
Créer, dans une base vide, une version réduite du schéma, puis la remplir. Trois tables :
Etudiant:idEtudiant, clé primaire ;nometprenom, obligatoires ;dateNaissance.Cours:idCours, clé primaire ;intitule, obligatoire ;volumeHoraire.Inscription:idEtudiant,idCoursetnote. La clé primaire est le couple. Supprimer un étudiant supprime ses inscriptions ; supprimer un cours qui a des inscrits est refusé.
Les données à insérer :
| idEtudiant | nom | prenom | dateNaissance |
|---|---|---|---|
| 1 | Durand | Claire | 2001-03-25 |
| 2 | Martin | Lucas | 2000-07-14 |
| 3 | Lefevre | Sophie | 2002-11-02 |
| 4 | Bernard | Tom | 2001-09-10 |
| idCours | intitule | volumeHoraire |
|---|---|---|
| 1 | Mathematiques | 30 |
| 2 | Physique | 24 |
| 3 | Informatique | 36 |
| idEtudiant | idCours | note |
|---|---|---|
| 1 | 1 | 14.5 |
| 1 | 3 | 16 |
| 2 | 1 | 11 |
| 2 | 2 | 9.5 |
| 3 | 2 | 13 |
| 4 | 3 | 12 |
Trois tables, leurs clés, et leurs données
Écrire le script qui crée les trois tables et y insère les données des trois tableaux. Les identifiants sont des INTEGER PRIMARY KEY, la note un REAL, les autres colonnes des TEXT ou des INTEGER ; les colonnes que l'énoncé ne dit pas obligatoires ne le sont pas.
La vérification lit les clés primaires des trois tables, les colonnes obligatoires, les clés étrangères d'Inscription avec ce qu'elles font d'une suppression, puis chaque inscription avec le nom de l'étudiant et l'intitulé du cours. Un SELECT ajouté en fin de script, pour voir le résultat, ne gêne pas la vérification.
« Exécuter » joue le script et montre l'état de la base qu'il laisse ; « Vérifier » compare cet état à celui attendu, sur 1 cas.
Sous MySQL, l'identifiant s'écrirait INT PRIMARY KEY AUTO_INCREMENT, le nom VARCHAR(50) et la note DECIMAL(4,2). La page exécute SQLite, où INTEGER PRIMARY KEY s'incrémente seul ; elle signale un AUTO_INCREMENT au lieu de l'exécuter.
Exercice 7, Filtrage sur les notes
Les inscriptions notées au moins 12
Écrire une requête qui renvoie le nom, le prénom et la note de chaque inscription notée au moins 12, de la meilleure note à la moins bonne.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Exercice 8, Comptage par cours
Le nombre d'inscrits de chaque cours
Écrire une requête qui renvoie l'intitulé de chaque cours et son nombre d'inscrits, du cours le plus suivi au moins suivi et, à nombre égal, par ordre alphabétique des intitulés.
Un cours qui n'a aucun inscrit figure dans le résultat, avec 0. Le départ est un premier jet, à essayer avant de le corriger.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Le second critère du ORDER BY départage les ex æquo : sans lui, deux cours à cinq inscrits sortent dans un ordre que rien ne fixe, et qui change d'un moteur à l'autre.
Exercice 9, Agrégats et filtrage de groupes
Les cours suivis et bien notés
Écrire une requête qui renvoie l'intitulé, le nombre d'inscrits et la moyenne des notes, arrondie à deux décimales par ROUND(..., 2), de chaque cours qui a au moins deux inscrits et une moyenne strictement supérieure à 11, de la meilleure moyenne à la moins bonne.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Sur la base du cours, Reseaux a deux inscrits mais 10.75 de moyenne : les deux conditions ne font pas double emploi, et la deuxième vérification montre un cours écarté par chacune. L'exercice Filtrer les groupes, sur la page Exercices, revient sur le partage entre WHERE et HAVING.
Exercice 10, Ce qui n'existe pas
Une question en « aucun » ne se répond pas en filtrant : les lignes cherchées sont précisément celles qui manquent. La requête doit construire l'absence.
Les cours sans étudiant parisien
Écrire une requête qui renvoie l'intitulé de chaque cours auquel aucun étudiant habitant Paris n'est inscrit.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Si la sous-requête rendait une seule valeur NULL, NOT IN ne rendrait plus aucune ligne, sans le moindre message. Ici la clé primaire interdit qu'idCours soit nulle, sous MySQL comme dans la page ; l'exercice 30 montre une colonne qui, elle, contient des NULL. Sans le filtre sur la ville, la requête cherche les cours sans aucun inscrit, et ne rend rien sur la base du cours : un résultat vide est une réponse, pas une panne. L'exercice Aucun inscrit de Paris, sur la page Exercices, pose la même question en variant les données.
Exercice 11, UPDATE et DELETE
Sur la base du module, dont la table Inscription déclare ON DELETE CASCADE vers Etudiant :
- L'étudiante Sophie Dupond, d'identifiant 3, a changé de nom : elle s'appelle désormais Dupont. Mettre à jour la table.
- L'étudiant Tom Durand, d'identifiant 4, quitte l'école. Le supprimer ainsi que toutes ses inscriptions.
- À quelle condition ses inscriptions disparaîtront-elles sans être supprimées une par une ?
Renommer, puis supprimer avec les inscriptions
Écrire le script qui renomme Sophie Dupond (identifiant 3) en Dupont, puis supprime Tom Durand (identifiant 4) avec toutes ses inscriptions.
La vérification lit, après le script, chaque étudiant (identifiant, nom, prénom) et chaque inscription. Certaines vérifications ajoutent d'abord un homonyme.
« Exécuter » joue le script et montre l'état de la base qu'il laisse ; « Vérifier » compare cet état à celui attendu, sur 3 cas, dont 1 caché.
La question 3 tient au moteur : une contrainte écrite dans le CREATE TABLE n'agit que s'il la vérifie. MySQL vérifie toujours les clés étrangères de ses tables InnoDB, et la page les a activées pour faire comme lui. Le bloc suivant supprime Sofia Petit, qui a une seule inscription, puis compte les inscriptions restantes.
PRAGMA foreign_keys = OFF; en tête du bloc et relancer : le compte passe de 24 à 25. Sofia Petit a disparu, son inscription est restée, et rien ne le signale : la base contient une inscription qui désigne un étudiant inexistant. Cette ligne est propre à SQLite, que MySQL refuserait ; son équivalent sous MySQL s'écrit SET FOREIGN_KEY_CHECKS = 0.
L'exercice Renommer et retirer, sur la clé, sur la page Exercices, refait ce geste sur deux autres étudiants.
Exercice 12, ALTER TABLE
Sur la base du module :
- Ajouter une colonne
mentionde typeVARCHAR(20)à la tableInscription, avec la valeur par défaut'Passable'. - Ajouter une contrainte
UNIQUEsur la colonneemailde la tableEtudiant. - Supprimer la colonne
dateNaissancede la tableEtudiant.
La base du module déclare déjà email unique : la question 2 suppose une table qui ne l'est pas encore, et se traite après le bloc, qui vérifie les deux autres.
Une colonne de plus, une colonne de moins
Écrire le script qui ajoute à Inscription la colonne mention, de type VARCHAR(20) et de valeur par défaut 'Passable', puis supprime la colonne dateNaissance d'Etudiant.
La vérification lit les colonnes des deux tables, la valeur par défaut de chaque colonne d'Inscription, et la mention de chaque inscription.
« Exécuter » joue le script et montre l'état de la base qu'il laisse ; « Vérifier » compare cet état à celui attendu, sur 3 cas, dont 1 caché.
La question 2. Sous MySQL, une contrainte s'ajoute par ALTER TABLE et se nomme, pour pouvoir la retirer plus tard par DROP CONSTRAINT uq_email :
SQLite, le moteur de la page, ne sait pas ajouter de contrainte à une table existante : il écrit la même règle par un index unique, CREATE UNIQUE INDEX uq_email ON Etudiant(email), que MySQL accepte aussi. Dans les deux écritures, le moteur contrôle d'abord l'existant, et refuse la contrainte si deux lignes se répètent déjà : une contrainte ne se déclare jamais sans avoir cherché les doublons qu'elle va interdire. Plusieurs NULL ne se comptent pas comme des doublons, et les deux étudiants de la base sans email passent.
Exercice 13, LIKE, BETWEEN et IS NULL
Trois requêtes sur le schéma de référence : les noms qui commencent par une lettre, un intervalle de volumes horaires, les notes non saisies.
Les noms qui commencent par D ou par M
Écrire une requête qui renvoie le nom et le prénom de chaque étudiant dont le nom commence par « D » ou par « M ».
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Les cours de 25 à 40 heures
Écrire une requête qui renvoie l'intitulé et le volume horaire de chaque cours de 25 à 40 heures, bornes comprises.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Les inscriptions sans note
Écrire une requête qui renvoie l'identifiant de l'étudiant et celui du cours de chaque inscription dont la note n'est pas encore saisie.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Les exercices L'email absent et Bornes incluses, sur la page Exercices, reprennent les deux derniers pièges.
1.Un énoncé dit qu'un étudiant suit plusieurs cours et qu'un cours accueille plusieurs étudiants. Que produit le MLD ?
2.La table Inscription déclare ON DELETE CASCADE vers Etudiant. Quand la suppression d'un étudiant emporte-t-elle ses inscriptions ?
Partie 3, Algèbre relationnelle
Exprimer les requêtes suivantes en utilisant les opérateurs σ (sélection), π (projection), ⨝ (jointure), ∪ (union), − (différence), ÷ (division).
Ces exercices reprennent L'algèbre relationnelle et ses arbres. SQL dit ce qu'on veut, l'algèbre dit dans quel ordre l'obtenir, ce que la partie 4 dessinera ensuite.
Les symboles s'écrivent avec la barre placée au-dessus de la zone de saisie ; au clavier, et, ou, non, <=, >= et le tiret conviennent aussi. Une table écrite dans un cas prend la place de la table du cours de même nom, les autres restent. À chaque vérification, l'arbre de l'expression se dessine, et chaque nœud se clique.
Exercice 14, Projection + sélection
Les inscrits en mathématiques
Écrire l'expression qui donne le nom et le prénom de chaque étudiant inscrit au cours dont l'intitulé est Mathematiques.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « trois inscriptions seulement »
| idEtudiant | idCours | note |
|---|---|---|
| 1 | 3 | 17 |
| 4 | 3 | 9 |
| 5 | 4 | 12 |
Les autres tables sont celles du cours.
L'exercice Sélection puis projection, sur la page Exercices, revient sur cet ordre.
Exercice 15, Sélection sur une table liée
Les cours de Tom Durand
Écrire l'expression qui donne l'intitulé de chaque cours que suit l'étudiant Tom Durand, dont l'identifiant est 4.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « un second Tom Durand s'est inscrit »
| idEtudiant | nom | prenom | dateNaissance | ville | idClasse | actif | |
|---|---|---|---|---|---|---|---|
| 4 | Durand | Tom | 2003-05-30 | tom.durand@ecole.fr | Nantes | 2 | 0 |
| 11 | Durand | Tom | 2005-02-11 | NULL | Lyon | 1 | 1 |
| idEtudiant | idCours | note |
|---|---|---|
| 4 | 2 | NULL |
| 4 | 4 | 7 |
| 11 | 6 | 12 |
Les autres tables sont celles du cours.
Exercice 16, Sélection avec condition numérique
Les étudiants qui ont une note sous 10
Écrire l'expression qui donne le nom et le prénom de chaque étudiant qui a obtenu au moins une note strictement inférieure à 10.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « une note de 10 tout juste, et deux notes sous 10 pour le même étudiant »
| idEtudiant | idCours | note |
|---|---|---|
| 1 | 3 | 10 |
| 2 | 1 | 8.5 |
| 2 | 3 | 9 |
| 5 | 1 | 12 |
Les autres tables sont celles du cours.
Exercice 17, Division relationnelle
Les étudiants inscrits à tous les cours
Écrire l'expression qui donne le nom et le prénom de chaque étudiant inscrit à tous les cours de la table Cours.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « deux cours seulement, Bases de donnees et Mathematiques »
| idCours | intitule | volumeHoraire | coefficient | idEnseignant |
|---|---|---|---|---|
| 1 | Bases de donnees | 30 | 2 | 1 |
| 3 | Mathematiques | 36 | 2.5 | 3 |
Les autres tables sont celles du cours.
L'exercice 27 écrit la même division en SQL. L'exercice Division par tous, sur la page Exercices, en pose une autre.
Exercice 18, Union
Les inscrits en mathématiques ou en physique
Écrire l'expression qui donne l'identifiant (idEtudiant) de chaque étudiant inscrit au cours Mathematiques, au cours Physique, ou aux deux.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « quatre inscriptions seulement »
| idEtudiant | idCours | note |
|---|---|---|
| 1 | 3 | 17 |
| 2 | 3 | 14 |
| 3 | 4 | 12 |
| 5 | 1 | 18 |
Les autres tables sont celles du cours.
L'union est ensembliste : un étudiant inscrit aux deux cours n'y figure qu'une fois. SQL la traduit par UNION, qui empile deux SELECT rendant les mêmes colonnes et retire les doublons.
La même union, en SQL
Écrire en SQL la requête de l'exercice : l'identifiant de chaque étudiant inscrit au cours Mathematiques, au cours Physique, ou aux deux, chacun une seule fois. Les cours se désignent par leur intitulé.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
L'étape suivante fait le compte de l'union de travers, à trouver.
Une union comptée trop vite
Une seule étape est fausse. Désigner laquelle.
Sur la base du module, cinq étudiants suivent les mathématiques et quatre la physique, et d'entre eux suivent les deux cours. La question posée : combien d'étudiants sont inscrits à l'un ou à l'autre ?
Exercice 19, Différence
Les inscrits en mathématiques qui ne suivent pas la physique
Écrire l'expression qui donne l'identifiant (idEtudiant) de chaque étudiant inscrit au cours Mathematiques sans être inscrit au cours Physique.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « quatre inscriptions seulement »
| idEtudiant | idCours | note |
|---|---|---|
| 1 | 3 | 17 |
| 2 | 3 | 14 |
| 2 | 4 | 11 |
| 3 | 4 | 12 |
Les autres tables sont celles du cours.
En SQL, EXCEPT traduit − de la même façon que UNION traduit ∪. SQLite, PostgreSQL et SQL Server le connaissent, et MySQL depuis sa version 8.0.31.
La même différence, en SQL
Écrire en SQL la requête de l'exercice : l'identifiant de chaque étudiant inscrit au cours Mathematiques sans être inscrit au cours Physique. Les cours se désignent par leur intitulé.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
L'exercice Différence pour dire « sans », sur la page Exercices, s'exerce au même opérateur.
π_{ville}(Etudiant) et SELECT ville FROM Etudiant diffèrent sur quoi ?
Partie 4, Arbres algébriques
Représenter chaque requête SQL sous forme d'arbre algébrique. Rappel : les feuilles sont les tables, les nœuds internes sont les opérations, et la racine est le résultat final. L'arbre se lit de bas en haut.
Ces exercices reprennent, eux aussi, L'algèbre relationnelle et ses arbres. Sur un arbre, la taille de chaque résultat intermédiaire devient visible, et donc le coût. Les deux premiers arbres se vérifient : l'expression écrite dessine le sien. Les trois suivants sortent de ce que le moteur calcule, ou demandent de juger un coût : ils gardent un corrigé replié.
Exercice 20, Arbre simple (sélection + projection)
L'arbre d'une sélection suivie d'une projection
Écrire l'expression d'algèbre relationnelle de la requête ci-dessus. Son arbre se dessine sous la zone de saisie à chaque vérification.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « une étudiante née le 1er janvier 2003 tout juste »
| idEtudiant | nom | prenom | dateNaissance | ville | idClasse | actif | |
|---|---|---|---|---|---|---|---|
| 2 | Diallo | Amine | 2003-11-02 | amine.diallo@ecole.fr | Lyon | 1 | 1 |
| 6 | Bernard | Yanis | 2002-09-08 | NULL | Paris | 2 | 1 |
| 11 | Roy | Lina | 2003-01-01 | NULL | Lyon | 1 | 1 |
Les autres tables sont celles du cours.
L'exercice Sélection puis projection, sur la page Exercices, pose le même arbre sur une autre table.
Exercice 21, Arbre avec LIKE
Les lignes de l'arbre au LIKE
- 1.
Sur la base du module, combien de lignes la sélection garde-t-elle ?
- 2.
Un second étudiant nommé Martin s'inscrit. Combien de lignes la projection rend-elle alors ?
Afficher la correction
π_{nom}
|
σ_{nom LIKE 'M%'}
|
EtudiantSe lit de bas en haut : les feuilles sont les tables, chaque nœud une opération appliquée au résultat du niveau inférieur.
LIKE 'M%' s'écrit en algèbre avec la même notation de sélection : la condition reste une condition sur les attributs de la relation. Le moteur des figures ne connaît pas LIKE, d'où cet arbre dessiné à la main. La sélection garde Martin, Moreau et Marchand. La requête SQL, elle, ne dédoublonne pas : avec un second Martin, elle rendrait quatre lignes, et sa traduction fidèle serait SELECT DISTINCT nom.
Exercice 22, Arbre avec BETWEEN
BETWEEN, sans BETWEEN
Écrire l'expression d'algèbre relationnelle de la requête ci-dessus. L'algèbre n'a pas d'opérateur BETWEEN.
Une condition ou une liste d'attributs s'écrit en indice, entre accolades, une chaîne entre apostrophes, un nombre décimal avec un point. Au clavier, et, ou, non, <>, <=, >= et le tiret de la différence conviennent aussi.
Écrire l'expression, puis « Vérifier » : elle est calculée sur 3 cas, dont 1 caché, et comparée à la correction calculée sur les mêmes tables.
Les tables du cas « trois cours à 20, 40 et 41 heures »
| idCours | intitule | volumeHoraire | coefficient | idEnseignant |
|---|---|---|---|---|
| 6 | Statistiques | 18 | 1 | 3 |
| 8 | Chimie | 20 | 1 | NULL |
| 9 | Optique | 40 | 1 | NULL |
| 10 | Geologie | 41 | 1 | NULL |
Les autres tables sont celles du cours.
Exercice 23, Arbre avec jointure et optimisation
Représenter en arbre la requête suivante, puis proposer une version optimisée :
Ce que coûte chaque arbre
- 1.
Combien de lignes la jointure du haut de l'arbre non optimisé construit-elle, avant la sélection ?
- 2.
Combien de lignes la sélection en garde-t-elle ?
- 3.
Dans l'arbre optimisé, où la sélection descend sur Cours et où la jointure qui en part est faite d'abord, combien de lignes compte la plus grosse jointure ?
Afficher la correction
Arbre non optimisé :
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | intitule |
|---|---|
| Martin | Informatique |
| Moreau | Informatique |
| Nguyen | Informatique |
Arbre optimisé (sélection poussée vers les feuilles) :
Cliquer sur un nœud pour voir la relation qu'il produit.
| nom | intitule |
|---|---|
| Martin | Informatique |
| Moreau | Informatique |
| Nguyen | Informatique |
Filtrer Cours avant la jointure le réduit à une ligne, et les deux jointures ne portent plus que sur 3 lignes au lieu de 25. L'ordre des jointures se choisit donc lui aussi : descendre la sélection ne suffit pas si la première jointure reste celle des deux grandes tables. L'exercice Pousser la sélection, sur la page Exercices, fait mesurer le même gain.
Exercice 24, Arbre avec agrégation
Les lignes de l'arbre d'agrégation
- 1.
Sur la base du module, combien de lignes la jointure construit-elle ?
- 2.
Combien de groupes l'agrégation forme-t-elle ?
- 3.
Combien de groupes passent le filtre du HAVING ?
Afficher la correction
π_{intitule, nbInscrits}
|
σ_{COUNT(*) >= 4} <-- HAVING
|
γ_{idCours, intitule; COUNT(*)} <-- GROUP BY + agrégat
|
⨝ (Cours.idCours = Inscription.idCours)
/ \
Cours InscriptionSe lit de bas en haut : les feuilles sont les tables, chaque nœud une opération appliquée au résultat du niveau inférieur.
γ (gamma) représente l'agrégation, GROUP BY et fonction d'agrégat, sous la forme γ_{colonnes de groupe ; agrégats}. De bas en haut : la jointure, 25 lignes ; l'agrégation par cours, sept groupes ; le filtre du HAVING, qui en laisse quatre, Algorithmique et Physique à quatre inscrits, Bases de donnees et Mathematiques à cinq ; la projection.
Le piège : placer le nœud σ du HAVING sous le nœud γ, par analogie avec la règle « pousser les sélections vers les feuilles » de l'exercice 23. Cette règle ne vaut que pour les sélections qui portent sur des colonnes. Celle-ci porte sur COUNT(*), qui n'existe qu'une fois γ franchi. C'est toute la différence entre WHERE et HAVING, lue sur un dessin.
1.Dans un arbre algébrique, où placer une sélection pour qu'il coûte le moins cher ?
2.SELECT nom, COUNT(*) FROM Etudiant GROUP BY ville pose quel problème ?
Partie 5, Requêtes complexes et imbriquées
Les quatre parties précédentes portaient sur une seule interrogation à la fois. Celle-ci en emboîte, comme le fait le chapitre SQL avancé : une requête a besoin d'un résultat qu'une autre requête calcule. Avant d'écrire une sous-requête, dire ce qu'elle rend, une valeur, une colonne ou une table. Une valeur se compare avec
=ou<; une colonne permetIN;EXISTS, lui, accepte n'importe quelle sous-requête reliée à la ligne extérieure, et c'est la forme à préférer dès qu'une négation entre en jeu.
Exercice 25, Jointures multiples
Le schéma des employés et de leurs projets, dans la base du module :
clé primaire clé étrangère, avec la table visée
Les employés des projets parisiens
Écrire une requête qui renvoie le nom et le prénom de chaque employé qui travaille sur au moins un projet d'un client situé à Paris, chacun une seule fois.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Exercice 26, Sous-requêtes imbriquées
Les cours des étudiants nés après le 1er juin 2004
Écrire une requête qui renvoie l'intitulé de chaque cours suivi par au moins un étudiant né après le 1er juin 2004, chacun une seule fois. Une date s'écrit '2004-06-01'.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Sur la base du cours, deux étudiantes sont nées après la date, Dupond Sophie et Nguyen Elsa, et leurs cours sont six sur sept : seul Statistiques manque. La requête rend les cours qui ont au moins un tel inscrit ; ceux qui n'ont que de tels inscrits demanderaient une négation, comme à l'exercice suivant.
Exercice 27, Double négation (tous les cours)
Les étudiants inscrits à tous les cours, en SQL
Écrire une requête qui renvoie le nom et le prénom de chaque étudiant inscrit à tous les cours de la table Cours.
Sur la base du cours, le résultat est vide : aucun étudiant ne suit les sept cours. La deuxième vérification fait inscrire une étudiante partout, pour que la requête ait quelqu'un à trouver.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Cette double négation est la traduction directe de la division relationnelle de l'exercice 17.
Après l'exercice : restreindre le diviseur, et deux autres écritures
Le bloc ci-dessous reprend la correction, sur la base du cours, où elle rend un résultat vide.
WHERE c.idCours IN (1, 3) AND NOT EXISTS ( à la place de WHERE NOT EXISTS ( dans la sous-requête du milieu, et relancer. Trois étudiants sortent, Martin, Diallo et Dupond : la requête fonctionne, et le résultat vide sur les sept cours était la bonne réponse.
Avec EXCEPT (SQLite, PostgreSQL, SQL Server, et MySQL depuis la version 8.0.31), la sous-requête du milieu devient une différence : les cours de la table, moins ceux de l'étudiant. Il ne doit rien en rester.
La sous-requête intérieure pourrait s'écrire c.idCours NOT IN (SELECT i.idCours FROM Inscription i WHERE i.idEtudiant = e.idEtudiant), juste ici parce qu'idCours, dans la clé primaire, n'est jamais NULL. Le jour où la liste contient un NULL, NOT IN n'est plus jamais vrai, et l'étudiant concerné est déclaré inscrit à tous les cours ; EXCEPT et les deux NOT EXISTS y résistent.
L'exercice Inscrit à tous, sur la page Exercices, reprend cette double négation.
Exercice 28, Analyse statistique
Trois questions, une requête pour chacune : la note maximale de chaque cours ; les cours dont la moyenne est inférieure à la moyenne générale de toutes les notes ; l'étudiant qui a la meilleure note de toute la base.
La note maximale de chaque cours
Écrire une requête qui renvoie l'intitulé de chaque cours et sa meilleure note, de la plus haute à la plus basse.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Les cours sous la moyenne générale
Écrire une requête qui renvoie l'intitulé et la moyenne, arrondie à deux décimales par ROUND(..., 2), de chaque cours dont la moyenne est strictement inférieure à la moyenne générale de toutes les notes, de la plus basse à la plus haute.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Les deux moyennes ne coïncident que si tous les cours ont le même nombre de notes ; sur la base, Mathematiques en pèse cinq et Statistiques une seule, son second inscrit n'étant pas noté. L'étape suivante refait le calcul de travers.
La moyenne générale, prise de travers
Une seule étape est fausse. Désigner laquelle.
Un cours de mathématiques a notes, de moyenne 14 ; un cours de statistiques n'en a qu'une, 10. Il s'agit de trouver la moyenne générale, celle que rend SELECT AVG(note) FROM Inscription, pour lui comparer chaque cours.
La meilleure note de la base, et qui l'a obtenue
Écrire une requête qui renvoie le nom, le prénom et la note de l'étudiant qui a obtenu la meilleure note de toute la base. S'ils sont plusieurs à l'avoir obtenue, la requête les renvoie tous.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
L'exercice Au-dessus de la moyenne, sur la page Exercices, compare lui aussi chaque ligne à une valeur que calcule une sous-requête.
Exercice 29, Sous-requête corrélée
Le meilleur de chaque cours
Écrire une requête qui renvoie, pour chaque cours, le nom, le prénom, l'intitulé du cours et la note de l'étudiant qui y a obtenu la meilleure note ; en cas d'ex æquo, tous.
Le résultat se range par intitulé, puis par nom.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
Sans le ORDER BY, l'ordre des lignes n'est fixé par rien, et MySQL ne rend pas le même que la page.
Après l'exercice : la même requête avec WITH
WITH donne un nom à une sous-requête, que la suite de la requête utilise comme une table :
L'exercice Le projet principal de chacun, sur la page Exercices, pose la même question sur les employés et leurs projets.
Exercice 30, EXISTS vs IN
Les étudiants qui ont une note sous 10, en SQL
Écrire une requête qui renvoie le nom et le prénom de chaque étudiant qui a au moins une inscription notée strictement sous 10, chacun une seule fois.
« Exécuter » montre ce que rend la requête ; « Vérifier » compare son résultat à celui attendu, sur 3 cas, dont 1 caché.
IN, EXISTS et la jointure avec DISTINCT rendent ici les mêmes cinq étudiants. Les deux premières ne parcourent qu'Etudiant, et ne peuvent pas produire de doublon ; la troisième le peut.
| Approche | Avantages | Inconvénients |
|---|---|---|
IN | Lisible, intuitif | NOT IN se vide si la sous-requête rend un NULL |
EXISTS | Résiste aux NULL en négation | Syntaxe plus verbeuse |
JOIN | Donne accès aux colonnes de la table jointe | Nécessite DISTINCT pour éviter les doublons |
Les performances se valent le plus souvent : l'optimiseur réécrit les deux formes, et sur cet exercice MySQL exécute IN et EXISTS selon le même plan, que EXPLAIN affiche (voir Exploiter une base). EXISTS sert à vérifier une existence, JOIN quand des colonnes de la table jointe sont nécessaires.
Le piège, en négatif : tant que la question est positive, IN et EXISTS donnent le même résultat ; la négation les sépare. Les trois requêtes suivantes cherchent les inscriptions dont la note ne figure pas parmi celles du cours 2, dont un inscrit n'est pas encore noté.
Un NULL dans la liste
- 1.
Combien de lignes rend la requête en NOT IN sur la base du module ?
- 2.
Combien en rend-elle une fois la sous-requête débarrassée de son NULL ?
- 3.
Combien en rend la version en NOT EXISTS ?
Elle ne rend aucune ligne, sans erreur ni avertissement. La sous-requête rend quatre notes, 16.5, 14.5, 10.5 et un NULL : note NOT IN (16.5, 14.5, 10.5, NULL) demande d'affirmer que la note diffère d'une valeur inconnue, la condition vaut inconnu, et WHERE ne garde que ce qui est vrai.
Vingt lignes cette fois : le passage de zéro à vingt tient à une seule valeur absente. Une requête juste pendant des mois devient silencieusement vide le jour où une saisie est laissée en blanc. NOT EXISTS résiste, parce qu'il teste l'existence d'une ligne, pas l'égalité avec une valeur :
Vingt-deux lignes : les vingt précédentes, plus les deux inscriptions dont la note est elle-même absente, qu'aucune note du cours 2 n'égale.
1.Sur la base du module, une jointure de Etudiant, Inscription et Cours rend 175 lignes. Est-ce normal ?
2.Quel test faut-il pour trouver les lignes dont une colonne n'a aucune valeur ?
Chapitre révisé en octobre 2026 · Une erreur dans ce chapitre ?