Jointures avancées
« Donne-moi le CA par client actif ayant commandé ce trimestre, avec leur dernière facture » : sans jointures avancées, c'est 5 requêtes + du code fragile.
Prérequis (cursus dev) : CRUD en SQL, jointures.
Pourquoi
« Donne-moi le CA par client actif ayant commandé ce trimestre, avec leur dernière facture » : sans jointures avancées, c'est 5 requêtes + du code fragile. Avec, une seule requête lisible — et 100× plus rapide.
Concepts
- INNER vs LEFT : INNER ne garde que les appariés ; LEFT garde tout de la gauche + NULL à droite. Choisir, c'est répondre à « les clients sans commande comptent-ils ? ».
- Self-join : joindre une table à elle-même (hiérarchies : employé → manager) via des alias (
eJOINm). Sans alias, ambiguïté garantie. - Semi/anti-jointures :
EXISTS(« a au moins un ») etNOT EXISTS(« n'a aucun ») — souvent plus rapides et plus lisibles queIN, et immunisés contre les NULL piégeux duNOT IN.
Exemple : actifs avec dernière facture
SELECT c.name, SUM(o.total) AS ca, MAX(o.created_at) AS derniere
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
AND o.created_at >= date_trunc('quarter', now())
WHERE c.active
GROUP BY c.name
HAVING COUNT(o.id) > 0;
Cas réel
Rapport « top clients » en IN (SELECT…) sur 2 M de lignes : 40 s + résultats faux dès qu'un NULL traîne. Réécrit en EXISTS + index : 300 ms et juste. Le NOT IN avec NULL ne rend jamais vrai — piège classique.
Pièges
NOT INavec NULL : toujours faux.NOT EXISTSà la place.- Oublier la condition temporelle dans le
ONvs leWHERE(avec LEFT : dans le WHERE, ça transforme en INNER !). SELECT *en jointure : colonnes dupliquées (id,id) qui cassent l'app. Nommer explicitement.
À retenir
LEFT vs INNER = question métier, alias en self-join, EXISTS > IN, conditions temporelles dans le ON.