Depuis que Postgres est sorti avec la possibilité de faire des LATERAL
jointures, j'ai lu à ce sujet, car je fais actuellement des vidages de données complexes pour mon équipe avec beaucoup de sous-requêtes inefficaces qui font que la requête globale prend quatre minutes ou plus.
Je comprends que les LATERAL
jointures peuvent m'aider, mais même après avoir lu des articles comme celui-ci de Heap Analytics, je ne suis toujours pas tout à fait à suivre.
Quel est le cas d'utilisation d'une LATERAL
jointure? Quelle est la différence entre une LATERAL
jointure et une sous-requête?
sql
postgresql
subquery
lateral-join
jdotjdot
la source
la source
apply
est le même que celuilateral
de la norme SQL)Réponses:
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'uneLATERAL
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 laFROM
clause. Commeunnest()
avec plusieurs paramètres dans Postgres 9.4 ou version ultérieure. Le manuel:Donc, cela fonctionne, mais ne peut pas être facilement remplacé par une sous-requête:
La virgule (
,
) dans laFROM
clause est une notation courte pourCROSS 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
listeVous pouvez également utiliser directement des fonctions de retour de set comme
unnest()
dans laSELECT
liste. Cela montrait un comportement surprenant avec plus d'une de ces fonctions dans la mêmeSELECT
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:
Comparaison:
dbfiddle pour pg 9.6 ici
dbfiddle pour pg 10 ici
Clarifier la désinformation
Le manuel:
Donc, ces deux requêtes sont valides (même si elles ne sont pas particulièrement utiles):
Bien que celui-ci ne soit pas:
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 @ Attilan'estpas valide.la source
LATERAL
sous - requête: gis.stackexchange.com/a/230070/7244La différence entre un non
lateral
et unelateral
jointure réside dans le fait que vous pouvez regarder la ligne de la table de gauche. Par exemple:Ce "regard vers l'extérieur" signifie que la sous-requête doit être évaluée plus d'une fois. Après tout,
t1.col1
peut prendre de nombreuses valeurs.En revanche, la sous-requête après une non-
lateral
jointure peut être évaluée une fois:Comme cela est requis sans
lateral
, la requête interne ne dépend en aucun cas de la requête externe. Unelateral
requête est un exemple decorrelated
requête, en raison de sa relation avec les lignes en dehors de la requête elle-même.la source
select * from table1 left join t2 using (col1)
comparer? Je ne sais pas quand une jointure utilisant / sur condition est insuffisante et il serait plus logique d'utiliser latéral.Premièrement, les applications latérales et croisées sont la même chose . Par conséquent, vous pouvez également lire sur Cross Apply. Comme il a été implémenté dans SQL Server depuis des lustres, vous trouverez plus d'informations à ce sujet puis Lateral.
Deuxièmement, selon ma compréhension , il n'y a rien que vous ne puissiez pas faire en utilisant une sous-requête au lieu d'utiliser latéral. Mais:
Pensez à la requête suivante.
Vous pouvez utiliser latéral dans cette condition.
Dans cette requête, vous ne pouvez pas utiliser de jointure normale, en raison de la clause limit. L'application latérale ou croisée peut être utilisée lorsqu'il n'y a pas de condition de jointure simple .
Il y a plus d'utilisations pour les applications latérales ou croisées, mais c'est la plus courante que j'ai trouvée.
la source
lateral
place deapply
. Peut-être que Microsoft a breveté la syntaxe?lateral
est dans le standard SQL maisapply
ne l'est pas.LEFT JOIN
nécessite une condition de jointure. Faites-leON TRUE
sauf si vous souhaitez restreindre d'une manière ou d'une autre.cross join
uneon
condition ou une conditionPersonne n'a souligné que vous pouvez utiliser des
LATERAL
requêtes pour appliquer une fonction définie par l'utilisateur sur chaque ligne sélectionnée.Par exemple:
C'est la seule façon dont je sais comment faire ce genre de chose dans PostgreSQL.
la source