Qué es un LATERAL
unirse?
La función se introdujo con PostgreSQL 9.3. El manual:
Subconsultas que aparecen en FROM
puede estar precedido por la palabra clave LATERAL
. Esto les permite hacer referencia a las columnas proporcionadas por FROM
anterior artículos. (Sin LATERAL
, cada subconsulta se evalúa de forma independiente y, por lo tanto, no puede hacer una referencia cruzada con ningún otro FROM
elemento.)
Funciones de tabla que aparecen en FROM
también puede estar precedido por la palabra clave LATERAL
, pero para funciones la palabra clave es opcional; Los argumentos de la función pueden contener referencias a columnas proporcionadas por FROM
artículos en cualquier caso.
Allí se dan ejemplos de código básico.
Más como un correlacionado subconsulta
UN LATERAL
join es más como una subconsulta correlacionada, no una subconsulta simple, en las expresiones a la derecha de un LATERAL
join se evalúan una vez por cada fila que queda, al igual que un correlacionado subconsulta - mientras que una subconsulta simple (expresión de tabla) se evalúa una vez solamente. (Sin embargo, el planificador de consultas tiene formas de optimizar el rendimiento para cualquiera).
Respuesta relacionada con ejemplos de código para ambos, uno al lado del otro, resolviendo el mismo problema:
- Optimizar la consulta GROUP BY para recuperar la fila más reciente por usuario
Para devolver más de una columna , un LATERAL
join suele ser más simple, limpio y rápido.
Además, recuerde que el equivalente de una subconsulta correlacionada es LEFT JOIN LATERAL ... ON true
:
- Llamar a una función de devolución de conjuntos con un argumento de matriz varias veces
Cosas que una subconsulta no puede hacer
Hay son cosas que un LATERAL
join puede hacerlo, pero una subconsulta (correlacionada) no puede (fácilmente). Una subconsulta correlacionada solo puede devolver un único valor, no varias columnas ni varias filas, con la excepción de las llamadas a funciones simples (que multiplican las filas de resultados si devuelven varias filas). Pero incluso ciertas funciones de devolución de conjuntos solo están permitidas en el FROM
cláusula. Como unnest()
con múltiples parámetros en Postgres 9.4 o posterior. El manual:
Esto solo está permitido en el FROM
cláusula;
Entonces esto funciona, pero no se puede (fácilmente) reemplazar con una subconsulta:
CREATE TABLE tbl (a1 int[], a2 int[]);
SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2); -- implicit LATERAL
La coma (,
) en el FROM
cláusula es una notación abreviada para CROSS JOIN
.LATERAL
se asume automáticamente para funciones de tabla.
Acerca del caso especial de UNNEST( array_expression [, ... ] )
:
- ¿Cómo se declara que una función de devolución de conjunto solo se permita en la cláusula FROM?
Funciones de devolución de conjuntos en SELECT
lista
También puede usar funciones de devolución de conjuntos como unnest()
en el SELECT
lista directamente. Esto solía exhibir un comportamiento sorprendente con más de una función de este tipo en el mismo SELECT
lista hasta Postgres 9.6. Pero finalmente se ha saneado con Postgres 10 y ahora es una alternativa válida (incluso si no es SQL estándar). Ver:
- ¿Cuál es el comportamiento esperado para varias funciones de devolución de conjuntos en la cláusula SELECT?
Basado en el ejemplo anterior:
SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM tbl;
Comparación:
dbfiddle para pg 9.6 aquí
dbfiddle para la página 10 aquí
Aclarar información errónea
El manual:
Para el INNER
y OUTER
tipos de combinación, se debe especificar una condición de combinación, es decir, exactamente una de NATURAL
, ON
condición_de_unión ,o USING
(join_column [,...]). Vea a continuación el significado.
Para CROSS JOIN
, ninguna de estas cláusulas puede aparecer.
Entonces estas dos consultas son válidas (aunque no particularmente útiles):
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;
Si bien este no lo es:
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
Por eso el código de ejemplo de Andomar es correcto (el CROSS JOIN
no requiere una condición de unión) y is de Attila no lo era.