data / sql
Jointures : INNER, LEFT, RIGHT, FULL
Explication
Ce que vous allez apprendre
- Comprendre pourquoi les données sont réparties dans plusieurs tables reliées
- Utiliser
INNER JOINpour combiner uniquement les lignes qui correspondent des deux côtés - Utiliser
LEFT JOIN/RIGHT JOIN/FULL OUTER JOINpour garder les lignes sans correspondance - Éviter le piège qui transforme silencieusement un
LEFT JOINenINNER JOIN - Écrire une jointure d'une table sur elle-même (self-join)
Dans quel contexte ?
Un développeur doit générer la liste de tous les clients de la table clients, y compris ceux qui n'ont jamais rien commandé dans la table commandes, pour une campagne marketing de relance. Un simple INNER JOIN ferait disparaître exactement les clients qu'il cherche à cibler : c'est le cas d'usage typique du LEFT JOIN détaillé dans cette leçon.
D'abord, pourquoi séparer les données du tout
Dans une base bien conçue, on ne met pas toutes les informations dans une seule grande table : les clients vivent dans "clients", leurs achats dans "commandes". C'est plus propre, mais ça crée un problème immédiat.
Le problème : comment relier les deux ?
Si les clients et les commandes sont dans deux tables séparées, comment retrouver le nom du client qui a passé une commande précise ? Il faut un moyen de "recoller" les deux tables ensemble.
La solution : la jointure
Une jointure relie des lignes de deux tables différentes qui partagent une information commune, ici l'identifiant du client. INNER JOIN est la version la plus simple : elle ne garde que les lignes qui ont une correspondance des DEUX côtés.
Une image pour bien visualiser
Imagine deux cercles qui se chevauchent (un diagramme de Venn). INNER JOIN ne garde que la zone d'intersection, là où les deux cercles se recouvrent.
Mais parfois, on veut garder ceux qui n'ont pas de correspondance
Une question comme "quels clients n'ont JAMAIS commandé ?" ne peut pas être résolue par un INNER JOIN, puisqu'il élimine justement les clients sans commande. Il faut un autre outil.
LEFT JOIN garde tout un côté
LEFT JOIN garde tout le cercle de gauche en entier, en complétant de NULL là où il n'y a pas de correspondance à droite. RIGHT JOIN fait l'inverse, et FULL OUTER JOIN garde les deux cercles entiers réunis.
| Type de jointure | Lignes conservées | Cas d'usage typique |
|---|---|---|
INNER JOIN | Uniquement les lignes qui matchent des deux côtés | clients ayant réellement commandé |
LEFT JOIN | Toutes les lignes de gauche + NULL à droite si absent | trouver les clients sans commande |
RIGHT JOIN | Toutes les lignes de droite + NULL à gauche si absent | rarement utilisé (on inverse le LEFT) |
FULL OUTER JOIN | Toutes les lignes des deux côtés | audit de cohérence entre deux tables |
CROSS JOIN | Produit cartésien (toutes combinaisons) | générer des variantes taille x couleur |
Le piège le plus fréquent de cette leçon
Placer une condition sur la table de droite dans le WHERE plutôt que dans le ON transforme silencieusement un LEFT JOIN en INNER JOIN : les lignes sans correspondance sont éliminées par le filtre, alors qu'on voulait justement les garder. La règle à retenir : les conditions propres à la jointure vont toujours dans le ON.
Piège fréquent
... LEFT JOIN commandes co ON co.client_id = c.id WHERE co.statut = 'livree' élimine tous les clients sans commande, car WHERE filtre après la jointure et NULL = 'livree' n'est jamais vrai. Écris plutôt la condition dans le ON : ON co.client_id = c.id AND co.statut = 'livree'.
Prérequis
Connaître les bases de WHERE et GROUP BY (leçons 2 et 4) aide à comprendre pourquoi une jointure mal placée dans le WHERE change le résultat.
Vers la suite
Après avoir su filtrer, trier, agréger et joindre, il reste une dernière brique avant les requêtes vraiment complexes : les sous-requêtes, vues dans la prochaine leçon.
Commandes & code
Jointures
-- Schéma de référence pour tous les exemples
-- clients(id, nom)
-- commandes(id, client_id, montant, produit_id)
-- produits(id, nom, prix)
-- INNER JOIN : uniquement les lignes qui matchent des deux côtés
SELECT c.nom AS client, co.montant
FROM clients c
INNER JOIN commandes co ON co.client_id = c.id;
-- LEFT JOIN : toutes les lignes de gauche, NULL côté droit si pas de match
-- Utile pour trouver les clients SANS commande
SELECT c.nom, co.id AS commande_id
FROM clients c
LEFT JOIN commandes co ON co.client_id = c.id
WHERE co.id IS NULL; -- clients qui n'ont jamais commandé
-- RIGHT JOIN : symétrique du LEFT JOIN (rarement utilisé, on préfère inverser le LEFT)
SELECT c.nom, co.montant
FROM commandes co
RIGHT JOIN clients c ON co.client_id = c.id;
-- FULL OUTER JOIN : toutes les lignes des deux côtés, NULL si pas de match
SELECT c.nom, co.montant
FROM clients c
FULL OUTER JOIN commandes co ON co.client_id = c.id;
-- Jointure sur plusieurs tables
SELECT c.nom AS client, p.nom AS produit, co.montant
FROM commandes co
JOIN clients c ON c.id = co.client_id
JOIN produits p ON p.id = co.produit_id
WHERE co.montant > 100;
-- Self-join : comparer une table à elle-même (ex: employés et leur manager)
SELECT e.nom AS employe, m.nom AS manager
FROM employes e
LEFT JOIN employes m ON e.manager_id = m.id;
-- CROSS JOIN : produit cartésien (toutes les combinaisons)
SELECT t.taille, c.couleur
FROM tailles t
CROSS JOIN couleurs c; -- génère toutes les variantes taille x couleur
-- Jointure avec condition additionnelle dans le ON
SELECT c.nom, co.montant
FROM clients c
LEFT JOIN commandes co ON co.client_id = c.id AND co.statut = 'livree';
-- différent de WHERE co.statut = 'livree' qui transformerait le LEFT en INNER de fait
-- USING quand les colonnes ont le même nom
SELECT co.id, c.nom
FROM commandes co
JOIN clients c USING (client_id); -- nécessite que les deux tables aient "client_id"
-- Simuler un FULL OUTER JOIN sans support natif (MySQL avant 8.0.31) via UNION
SELECT c.nom, co.montant FROM clients c LEFT JOIN commandes co ON co.client_id = c.id
UNION
SELECT c.nom, co.montant FROM clients c RIGHT JOIN commandes co ON co.client_id = c.id;Résumé
INNER JOIN: intersection ;LEFT/RIGHT JOIN: tout un côté + NULL ;FULL OUTER JOIN: union.- Une condition sur la table de droite dans
WHERE(au lieu duON) annule l'effet duLEFT JOIN. CROSS JOINgénère un produit cartésien, à utiliser avec précaution (explosion combinatoire).- Le self-join relie une table à elle-même via un alias différent de chaque côté.
Exercices pratiques
Mission : cibler les clients jamais convertis pour une campagne de relance
Objectif : Utiliser correctement LEFT JOIN pour isoler des lignes sans correspondance, et corriger un piège classique ON/WHERE.
Contexte
L'équipe marketing veut relancer par email tous les clients de la table clients qui n'ont jamais rien commandé dans la table commandes, pour leur envoyer un code de bienvenue. Un premier essai avec INNER JOIN a donné une liste vide de "clients inactifs", ce qui a mis la puce à l'oreille de l'équipe.