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.

