Le LATERAL JOIN est l'une des fonctionnalités SQL les plus méconnues, et pourtant régulièrement présentes dans les entretiens data senior. En une phrase : un LATERAL JOIN permet à une sous-requête de faire référence aux colonnes de la table qui la précède dans la clause FROM, ce qu'une jointure classique ne permet pas. Cette capacité ouvre la porte à des requêtes bien plus expressives, notamment pour les analyses de séries temporelles, les top-N par groupe ou les calculs corrélés. Si vous préparez un entretien technique ou cherchez à écrire des requêtes plus propres, maîtriser cette syntaxe est un véritable avantage. Ce guide vous explique tout, de la syntaxe de base aux cas d'usage réels, avec des exemples prêts à exécuter.
📌 Ce qu'il faut retenir
- Un
LATERAL JOINévalue sa sous-requête ligne par ligne en accédant aux colonnes de la table externe. - Il est disponible nativement en PostgreSQL, MySQL 8.0+ et BigQuery ; SQL Server utilise l'équivalent
CROSS APPLY. - Le principal cas d'usage est le top-N par groupe, plus lisible qu'une fenêtre de ranking.
- Une jointure
LATERALpeut retourner 0 ligne par défaut : utilisezLEFT JOIN LATERAL ... ON TRUEpour conserver toutes les lignes de gauche.
Pourquoi le LATERAL JOIN change la donne
Dans une requête SQL classique, chaque table de la clause FROM est indépendante des autres. Une sous-requête dans le FROM ne peut pas "regarder" les valeurs d'une table placée avant elle dans la liste. C'est exactement cette contrainte que le LATERAL lève.
Concrètement, imaginez une table clients et une table commandes. Vous voulez, pour chaque client, récupérer ses 3 dernières commandes. Sans LATERAL, vous devez passer par une fonction fenêtre avec ROW_NUMBER ou une sous-requête corrélée dans le SELECT. Avec LATERAL, la logique devient linéaire et beaucoup plus lisible.
Ce mécanisme s'apparente à une boucle implicite : pour chaque ligne de la table principale, la sous-requête est réévaluée avec les valeurs courantes de cette ligne.
Syntaxe de base du LATERAL JOIN
Voici la forme canonique en PostgreSQL :
SELECT c.nom, d.montant, d.date_commande
FROM clients c
JOIN LATERAL (
SELECT montant, date_commande
FROM commandes
WHERE commandes.client_id = c.id
ORDER BY date_commande DESC
LIMIT 3
) d ON TRUE;
La clause ON TRUE indique qu'il n'y a pas de condition de jointure supplémentaire : toutes les lignes produites par la sous-requête sont conservées. Notez que c.id est accessible à l'intérieur de la sous-requête grâce au mot-clé LATERAL.
Pour conserver les clients sans aucune commande, remplacez JOIN par LEFT JOIN :
SELECT c.nom, d.montant, d.date_commande
FROM clients c
LEFT JOIN LATERAL (
SELECT montant, date_commande
FROM commandes
WHERE commandes.client_id = c.id
ORDER BY date_commande DESC
LIMIT 3
) d ON TRUE;
💡 Bon à savoir
En PostgreSQL, la fonction UNNEST() utilisée dans le FROM est implicitement un LATERAL. Inutile donc d'écrire le mot-clé explicitement dans ce cas précis.
LATERAL vs CROSS APPLY : quelle différence ?
SQL Server et Azure SQL ne connaissent pas le mot-clé LATERAL. Ils proposent à la place CROSS APPLY (équivalent du JOIN LATERAL) et OUTER APPLY (équivalent du LEFT JOIN LATERAL). La logique est identique, seule la syntaxe change.
| Concept | PostgreSQL / MySQL / BigQuery | SQL Server / Azure SQL | Comportement |
|---|---|---|---|
| Jointure latérale classique | JOIN LATERAL ... ON TRUE |
CROSS APPLY |
Exclut les lignes sans correspondance |
| Jointure latérale optionnelle | LEFT JOIN LATERAL ... ON TRUE |
OUTER APPLY |
Conserve toutes les lignes de gauche (NULL si vide) |
| Disponibilité | PostgreSQL 9.3+, MySQL 8.0+, BigQuery | SQL Server 2005+ | — |
