← Guides

Les jointures SQL expliquées avec des exemples réels (INNER, LEFT, RIGHT, FULL)

Tous les types de JOIN SQL sur un petit jeu clients/commandes, avec les erreurs qui dupliquent ou suppriment des lignes sans prévenir.

SQL · 9 min de lecture

Le jeu de données

Nous utilisons deux tables : clients(id, nom, pays) avec 4 lignes et commandes(id, client_id, montant, cree_le) avec 6 lignes. Un client n'a jamais commandé et une commande référence un client supprimé. Ces deux cas limites expliquent toutes les différences entre les jointures.

INNER JOIN : uniquement les correspondances

Un INNER JOIN ne renvoie que les lignes présentes des deux côtés. Le client sans commande et la commande orpheline disparaissent. À utiliser pour le chiffre d'affaires par client actif.

SELECT c.nom, SUM(o.montant) AS ca
FROM clients c
INNER JOIN commandes o ON o.client_id = c.id
GROUP BY c.nom
ORDER BY ca DESC;

LEFT JOIN : tout garder à gauche

Le LEFT JOIN conserve tous les clients, même sans commande (colonnes à NULL). Idéal pour « quels clients n'ont jamais commandé ? » avec WHERE o.id IS NULL. Piège fréquent : filtrer la table de droite dans le WHERE (WHERE o.montant > 100) transforme silencieusement le LEFT JOIN en INNER JOIN. Placez cette condition dans le ON.

SELECT c.nom
FROM clients c
LEFT JOIN commandes o ON o.client_id = c.id
WHERE o.id IS NULL;

RIGHT et FULL OUTER JOIN

Le RIGHT JOIN est un LEFT JOIN inversé ; on le réécrit généralement en LEFT JOIN. Le FULL OUTER JOIN garde les lignes sans correspondance des deux côtés : parfait pour rapprocher un export CRM et la facturation. MySQL ne le supporte pas : on l'émule avec LEFT JOIN UNION RIGHT JOIN.

Le piège des doublons

Joindre clients, commandes puis paiements multiplie chaque client par commandes × paiements, et les sommes sont gonflées. Agrégez d'abord chaque table enfant dans une CTE, puis joignez les résultats agrégés.

WITH o AS (
  SELECT client_id, SUM(montant) AS commande
  FROM commandes GROUP BY client_id
), p AS (
  SELECT client_id, SUM(montant) AS paye
  FROM paiements GROUP BY client_id
)
SELECT c.nom, o.commande, p.paye
FROM clients c
LEFT JOIN o ON o.client_id = c.id
LEFT JOIN p ON p.client_id = c.id;

Checklist avant production

1) Comptez les lignes avant/après la jointure. 2) Indexez les colonnes de jointure. 3) Listez les colonnes plutôt que SELECT *. 4) Décidez du traitement des NULL (COALESCE(o.montant, 0)). Dans FormulAI, décrivez vos tables et le résultat attendu : la requête générée est accompagnée d'une explication à confronter à cette liste.