Anaïs Sparesotto
SQL · AvancéIntermédiaire≈ 2h15 · 7 chapitres

SQL Avancé : optimisation des bases de données

Jointures avancées, CTE récursives, fonctions de fenêtrage, index, EXPLAIN, isolation transactionnelle. Pour écrire des requêtes qui tiennent à l'échelle.

À la fin du cours, tu sais

  • Maîtriser les jointures (LEFT, FULL, LATERAL) et les anti-jointures
  • Utiliser CTE et CTE récursives pour des requêtes lisibles
  • Exploiter les fonctions de fenêtrage (ROW_NUMBER, LAG, cumul)
  • Lire un plan EXPLAIN ANALYZE pour diagnostiquer une requête lente
  • Choisir le bon index (B-tree, partiel, composé, GIN)
  • Comprendre les niveaux d'isolation et leurs anomalies

Prérequis

  • Connaître les bases SQL (SELECT, INSERT, UPDATE, JOIN simple)
  • Avoir accès à une base PostgreSQL ou MySQL pour tester
Chapitre 11 / 10

Étape 1 sur 10 : Jointures avancées

Chapitre 1

Jointures avancées

Tu connais INNER JOIN. On attaque les cas réels : données manquantes, anti-jointures, jointures latérales.

Tu maîtrises l'INNER JOIN et le LEFT JOIN de base. Ce chapitre attaque les jointures telles qu'on les rencontre vraiment en production : celles qui répondent à des questions plus fines que « croise A et B ». Trouver ce qui manque, réconcilier deux référentiels incohérents, ou récupérer les N derniers éléments par groupe — autant de besoins réels qui demandent des motifs de jointure plus élaborés.

Le premier motif à maîtriser est l'anti-jointure : trouver les lignes d'une table qui n'ont aucune correspondance dans une autre (clients sans commande, produits jamais vendus). On peut l'écrire avec LEFT JOIN ... WHERE droite.id IS NULL, mais la variante NOT EXISTS est souvent plus rapide et surtout plus sûre. Car il y a un piège redoutable : NOT IN sur une sous-requête renvoie zéro ligne dès qu'un NULL s'y glisse, à cause de la logique à trois valeurs de SQL (une comparaison avec NULL vaut « inconnu », jamais « vrai »). Retiens la règle : pour une anti-jointure, préfère toujours NOT EXISTS.

Deux autres outils complètent ta boîte. Le FULL OUTER JOIN garde toutes les lignes des deux tables, avec des NULL là où il n'y a pas de correspondance : idéal pour réconcilier deux sources de données et repérer ce qui existe d'un côté mais pas de l'autre. Et la jointure LATERAL (en PostgreSQL) permet une sous-requête corrélée performante : pour chaque ligne de la table principale, elle exécute une sous-requête qui peut référencer cette ligne. C'est la solution élégante au classique « les 3 dernières commandes de chaque client », un besoin que les jointures ordinaires peinent à exprimer proprement.

Anti-jointure : trouver ce qui manque

-- Clients sans aucune commande (anti-jointure)
SELECT c.id, c.nom
FROM clients c
LEFT JOIN commandes o ON o.client_id = c.id
WHERE o.id IS NULL;

-- Variante avec NOT EXISTS (souvent plus rapide)
SELECT c.id, c.nom
FROM clients c
WHERE NOT EXISTS (
  SELECT 1 FROM commandes o WHERE o.client_id = c.id
);

NOT IN avec NULL : piège classique

NOT IN (sous-requête) retourne 0 ligne dès qu'un NULL apparaît dans la sous-requête, à cause de la logique trivaluée SQL. Préfère NOT EXISTS, toujours.

FULL OUTER JOIN

Garde toutes les lignes des deux côtés, NULL où il n'y a pas de correspondance. Utile pour réconcilier deux référentiels.

SELECT COALESCE(a.id, b.id) AS id, a.donnee_source, b.donnee_cible
FROM source a
FULL OUTER JOIN cible b ON a.id = b.id;

LATERAL : sous-requête corrélée performante (Postgres)

-- Pour chaque client, les 3 dernières commandes
SELECT c.id, c.nom, d.id AS commande_id, d.total
FROM clients c
LEFT JOIN LATERAL (
  SELECT id, total
  FROM commandes
  WHERE client_id = c.id
  ORDER BY cree_le DESC
  LIMIT 3
) d ON true;

Tu veux ce cours pour ton équipe ?

Je peux adapter et animer ce cours pour tes formateur·ices ou tes apprenant·es, en présentiel ou en distanciel. Parlons-en pendant l'audit gratuit.

Réserver un audit gratuit →