Retour au cours

data / sql

Jointures : INNER, LEFT, RIGHT, FULL

Leçon 51 exercice

Explication

Ce que vous allez apprendre

  • Comprendre pourquoi les données sont réparties dans plusieurs tables reliées
  • Utiliser INNER JOIN pour combiner uniquement les lignes qui correspondent des deux côtés
  • Utiliser LEFT JOIN / RIGHT JOIN / FULL OUTER JOIN pour garder les lignes sans correspondance
  • Éviter le piège qui transforme silencieusement un LEFT JOIN en INNER 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 jointureLignes conservéesCas d'usage typique
INNER JOINUniquement les lignes qui matchent des deux côtésclients ayant réellement commandé
LEFT JOINToutes les lignes de gauche + NULL à droite si absenttrouver les clients sans commande
RIGHT JOINToutes les lignes de droite + NULL à gauche si absentrarement utilisé (on inverse le LEFT)
FULL OUTER JOINToutes les lignes des deux côtésaudit de cohérence entre deux tables
CROSS JOINProduit 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

sql
-- 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 du ON) annule l'effet du LEFT JOIN.
  • CROSS JOIN gé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

1 disponible
1

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.

Résoudre l’exercice →