Plus comme une sous-requête corrélée
Une LATERAL
jointure (Postgres 9.3 ou version ultérieure) ressemble plus à une sous - requête corrélée , pas à une sous-requête simple. Comme l'a souligné Andomar , une fonction ou une sous-requête à droite d'une LATERAL
jointure doit être évaluée une fois pour chaque ligne à gauche - tout comme une sous-requête corrélée - tandis qu'une sous-requête simple (expression de table) n'est évaluée qu'une seule fois . (Le planificateur de requêtes a cependant des moyens d'optimiser les performances pour l'un ou l'autre.)
Cette réponse connexe a des exemples de code pour les deux côte à côte, résolvant le même problème:
Pour le retour plus d'une colonne , une LATERAL
jointure est généralement plus simple, plus propre et plus rapide.
Souvenez-vous également que l'équivalent d'une sous-requête corrélée est LEFT JOIN LATERAL ... ON true
:
Lisez le manuel sur LATERAL
Il fait plus autorité que tout ce que nous allons mettre dans les réponses ici:
Choses qu'une sous-requête ne peut pas faire
Il y a des choses qu'une LATERAL
jointure peut faire, mais une sous-requête (corrélée) ne le peut pas (facilement). Une sous-requête corrélée ne peut renvoyer qu'une seule valeur, pas plusieurs colonnes ni plusieurs lignes - à l'exception des appels de fonction nus (qui multiplient les lignes de résultat si elles renvoient plusieurs lignes). Mais même certaines fonctions de retour d'ensemble ne sont autorisées que dans la FROM
clause. Comme unnest()
avec plusieurs paramètres dans Postgres 9.4 ou version ultérieure. Le manuel:
Ceci n'est autorisé que dans la FROM
clause;
Donc, cela fonctionne, mais ne peut pas être facilement remplacé par une sous-requête:
CREATE TABLE tbl (a1 int[], a2 int[]);
SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2); -- implicit LATERAL
La virgule ( ,
) dans la FROM
clause est une notation courte pour CROSS JOIN
.
LATERAL
est supposé automatiquement pour les fonctions de table.
En savoir plus sur le cas particulier de UNNEST( array_expression [, ... ] )
:
Fonctions de retour d'ensemble dans la SELECT
liste
Vous pouvez également utiliser directement des fonctions de retour de set comme unnest()
dans la SELECT
liste. Cela montrait un comportement surprenant avec plus d'une de ces fonctions dans la même SELECT
liste jusqu'à Postgres 9.6. Mais il a finalement été nettoyé avec Postgres 10 et est une alternative valide maintenant (même si ce n'est pas le SQL standard). Voir:
S'appuyant sur l'exemple ci-dessus:
SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM tbl;
Comparaison:
dbfiddle pour pg 9.6 ici
dbfiddle pour pg 10 ici
Clarifier la désinformation
Le manuel:
Pour les types de jointure INNER
et OUTER
, une condition de jointure doit être spécifiée, à savoir exactement l'une des conditions NATURAL
, ON
join_condition , ou USING
( join_column [, ...]). Voir ci-dessous pour la signification.
Car CROSS JOIN
aucune de ces clauses ne peut apparaître.
Donc, ces deux requêtes sont valides (même si elles ne sont pas particulièrement utiles):
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t ON TRUE;
SELECT *
FROM tbl t, LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
Bien que celui-ci ne soit pas:
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
C'est pourquoi l' exemple de code de @ Andomar est correct (le CROSS JOIN
ne nécessite pas de condition de jointure) et celui de @ Attila n'est pas valide.
apply
est le même que celuilateral
de la norme SQL)