Prérequis : requêtes de sélection SQL , le modèle relationnel (clé étrangère)
À l’issue de ce chapitre, vous saurez :
- expliquer pourquoi une jointure est nécessaire pour croiser des données de plusieurs tables ;
- écrire une jointure SQL avec la syntaxe
JOIN ... ON; - écrire une jointure SQL avec la syntaxe
WHERE(produit cartésien filtré) ; - réaliser une jointure sur trois tables.
Pourquoi les jointures ?
Le modèle relationnel répartit les données dans plusieurs tables pour éviter la redondance. Mais quand on souhaite combiner des informations provenant de tables différentes, il faut les relier : c’est le rôle de la jointure.
Tables d’exemple
On considère une base de données de gestion scolaire avec trois tables :
Eleves :
| id_eleve | nom | prenom | id_classe |
|---|---|---|---|
| 1 | Dupont | Marie | 101 |
| 2 | Martin | Lucas | 102 |
| 3 | Leroy | Emma | 101 |
| 4 | Petit | Hugo | 102 |
Classes :
| id_classe | nom_classe | salle |
|---|---|---|
| 101 | Terminale A | B204 |
| 102 | Terminale B | C112 |
Matieres :
| id_matiere | nom_matiere | #id_classe | enseignant |
|---|---|---|---|
| 1 | NSI | 101 | M. Dupuis |
| 2 | Mathématiques | 101 | Mme Roche |
| 3 | NSI | 102 | M. Dupuis |
| 4 | Physique | 102 | M. Laurent |
L’attribut id_classe dans Eleves est une clé étrangère qui référence Classes.id_classe. C’est cet attribut commun qui permet de relier les deux tables.
Comprendre la jointure pas à pas
On souhaite afficher, pour chaque élève, son nom et le nom de sa classe.
Étape 1 : identifier l’attribut commun.
L’attribut id_classe est présent dans les deux tables : c’est la clé étrangère dans Eleves et la clé primaire dans Classes.
Étape 2 : faire correspondre les lignes.
Pour Marie Dupont, id_classe = 101. Dans Classes, la ligne 101 correspond à « Terminale A ». On associe donc Marie à « Terminale A ».
Étape 3 : construire le résultat.
| nom | prenom | nom_classe | salle |
|---|---|---|---|
| Dupont | Marie | Terminale A | B204 |
| Martin | Lucas | Terminale B | C112 |
| Leroy | Emma | Terminale A | B204 |
| Petit | Hugo | Terminale B | C112 |
Syntaxe SQL : JOIN … ON
C’est la syntaxe recommandée. Elle exprime clairement quelle table on rejoint et sur quelle condition.
SELECT Eleves.nom, Eleves.prenom, Classes.nom_classe
FROM Eleves
JOIN Classes ON Eleves.id_classe = Classes.id_classe;
La clause JOIN Classes indique qu’on combine la table Eleves avec Classes. La condition ON Eleves.id_classe = Classes.id_classe précise qu’on relie les lignes dont la valeur de id_classe est identique.
On peut ajouter un filtre avec WHERE :
SELECT Eleves.nom, Eleves.prenom
FROM Eleves
JOIN Classes ON Eleves.id_classe = Classes.id_classe
WHERE Classes.salle = 'B204';
Résultat : Dupont Marie, Leroy Emma (les élèves de la salle B204).
Syntaxe SQL : WHERE (produit cartésien filtré)
Une autre syntaxe, plus ancienne, consiste à lister les tables dans FROM et à exprimer la condition de jointure dans WHERE :
SELECT Eleves.nom, Eleves.prenom, Classes.nom_classe
FROM Eleves, Classes
WHERE Eleves.id_classe = Classes.id_classe;
Le résultat est identique. Sans la condition WHERE, le SGBD calculerait le produit cartésien (toutes les combinaisons possibles de lignes des deux tables, soit $4 \times 2 = 8$ lignes), ce qui ne ferait pas sens.
Les deux syntaxes sont équivalentes, mais JOIN ... ON est préférable car elle sépare clairement la condition de jointure des filtres (WHERE).
Jointure sur trois tables
Pour combiner trois tables, on enchaîne les clauses JOIN.
Afficher le nom de chaque élève et les matières enseignées dans sa classe :
SELECT Eleves.nom, Eleves.prenom, Matieres.nom_matiere, Matieres.enseignant
FROM Eleves
JOIN Classes ON Eleves.id_classe = Classes.id_classe
JOIN Matieres ON Classes.id_classe = Matieres.id_classe;
Résultat :
| nom | prenom | nom_matiere | enseignant |
|---|---|---|---|
| Dupont | Marie | NSI | M. Dupuis |
| Dupont | Marie | Mathématiques | Mme Roche |
| Leroy | Emma | NSI | M. Dupuis |
| Leroy | Emma | Mathématiques | Mme Roche |
| Martin | Lucas | NSI | M. Dupuis |
| Martin | Lucas | Physique | M. Laurent |
| Petit | Hugo | NSI | M. Dupuis |
| Petit | Hugo | Physique | M. Laurent |
On peut bien sûr filtrer : quels élèves ont M. Dupuis comme enseignant ?
SELECT Eleves.nom, Eleves.prenom
FROM Eleves
JOIN Classes ON Eleves.id_classe = Classes.id_classe
JOIN Matieres ON Classes.id_classe = Matieres.id_classe
WHERE Matieres.enseignant = 'M. Dupuis';
Résultat : tous les élèves des deux classes (car M. Dupuis enseigne la NSI dans les deux classes).
Compter avec une jointure
Les fonctions d’agrégation fonctionnent aussi avec les jointures.
Combien d’élèves sont en Terminale A ?
SELECT COUNT(*)
FROM Eleves
JOIN Classes ON Eleves.id_classe = Classes.id_classe
WHERE Classes.nom_classe = 'Terminale A';
Résultat : 2 (Dupont Marie et Leroy Emma).
Vérifiez votre compréhension
- Pourquoi a-t-on besoin d’une jointure pour afficher le nom d’un élève et le nom de sa classe ?
Réponse
Parce que le nom de l'élève est dans la tableEleveset le nom de la classe est dans la tableClasses. Pour combiner ces informations, il faut relier les deux tables via leur attribut communid_classe. C'est exactement le rôle d'une jointure. - Que se passe-t-il si on oublie la condition de jointure (
ONouWHERE) ?Réponse
Le SGBD calcule le produit cartésien : il combine chaque ligne de la première table avec chaque ligne de la seconde. Si la première a 4 lignes et la seconde 2, on obtient $4 \times 2 = 8$ lignes, dont la plupart n'ont pas de sens (par exemple, associer Marie à la Terminale B alors qu'elle est en Terminale A). - Dans la requête
SELECT E.nom FROM Eleves E JOIN Classes C ON E.id_classe = C.id_classe, que signifientEetC?Réponse
Ce sont des alias :EremplaceElevesetCremplaceClasses. Cela permet d'écrire des requêtes plus courtes et plus lisibles, surtout quand les noms de tables sont longs ou quand on joint plusieurs tables.
- Une jointure combine les lignes de deux (ou plusieurs) tables en se basant sur un attribut commun, typiquement une clé étrangère.
- La syntaxe recommandée est
JOIN ... ON:SELECT ... FROM Table1 JOIN Table2 ON Table1.clé = Table2.clé. - La syntaxe
FROM Table1, Table2 WHERE Table1.clé = Table2.cléest équivalente mais moins explicite. - Sans condition de jointure, on obtient le produit cartésien (toutes les combinaisons), ce qui n’a généralement pas de sens.
- On peut enchaîner plusieurs
JOINpour relier trois tables ou plus. - Les fonctions d’agrégation (
COUNT,AVG, etc.) fonctionnent aussi avec les jointures.