- Categorias:
Junção lateral¶
Em uma cláusula FROM, a palavra-chave LATERAL permite uma exibição em linha para referenciar colunas de uma expressão de tabela que precede aquela visão em linha.
Uma junção lateral comporta-se mais como uma subconsulta correlata do que como a maioria de JOINs. Uma junção lateral se comporta como se o servidor executasse um loop semelhante ao seguinte:
for each row in left_hand_table LHT:
execute right_hand_subquery RHS using the values from the current row in the LHT
Ao contrário da saída de uma junção não lateral, a saída de uma junção lateral inclui apenas as linhas geradas a partir da exibição em linha. As linhas do lado esquerdo não precisam ser unidas ao lado direito porque as linhas do lado esquerdo já foram levadas em consideração ao serem passadas para a exibição em linha.
Neste tópico:
Sintaxe¶
SELECT ...
FROM <left_hand_table_expression>, LATERAL ( <inline_view> )
...
left_hand_table_expression
Esta é uma fonte de linhas, como por exemplo:
Uma tabela.
Uma exibição.
Uma subconsulta.
Uma função de tabela.
O resultado de uma junção anterior.
inline_view
inline_view
pode ser:Uma exibição em linha (uma exibição definida dentro da instrução, e válida apenas pela duração da instrução).
Uma subconsulta.
Uma função de tabela (ou uma função de tabela interna como FLATTEN ou uma função de tabela definida pelo usuário (UDTF)).
inline_view
não pode ser uma tabela.
Notas de uso¶
A exibição em linha após a palavra-chave LATERAL pode referenciar colunas somente da própria exibição em linha e das tabelas à esquerda da exibição em linha na cláusula FROM.
SELECT * FROM table_reference_me, LATERAL (...), table_do_not_reference_me ...
Embora a exibição em linha normalmente faça referência a uma ou mais colunas do
left_hand_table_expression
, não é necessário fazer isso.Assim como a sintaxe INNER JOIN pode usar a vírgula ou as palavras “INNER JOIN”, uma junção lateral também pode usar a vírgula ou as palavras INNER JOIN.
Você não pode especificar a cláusula ON, USING ou NATURAL JOIN em uma função de tabela lateral (diferente de SQL UDTF) e não pode especificar a cláusula ON, USING ou NATURAL JOIN em uma junção lateral externa a uma função de tabela (diferente de SQL UDTF).
Para obter detalhes, consulte as Notas de Uso no tópico JOIN.
Exemplos¶
Este exemplo utiliza os dados mostrados abaixo:
CREATE TABLE departments (department_id INTEGER, name VARCHAR); CREATE TABLE employees (employee_ID INTEGER, last_name VARCHAR, department_ID INTEGER, project_names ARRAY);INSERT INTO departments (department_ID, name) VALUES (1, 'Engineering'), (2, 'Support'); INSERT INTO employees (employee_ID, last_name, department_ID) VALUES (101, 'Richards', 1), (102, 'Paulson', 1), (103, 'Johnson', 2);
Exemplo básico¶
Este exemplo mostra um LATERAL JOIN com uma subconsulta.
SELECT * FROM departments AS d, LATERAL (SELECT * FROM employees AS e WHERE e.department_ID = d.department_ID) AS iv2 ORDER BY employee_ID; +---------------+-------------+-------------+-----------+---------------+---------------+ | DEPARTMENT_ID | NAME | EMPLOYEE_ID | LAST_NAME | DEPARTMENT_ID | PROJECT_NAMES | |---------------+-------------+-------------+-----------+---------------+---------------| | 1 | Engineering | 101 | Richards | 1 | NULL | | 1 | Engineering | 102 | Paulson | 1 | NULL | | 2 | Support | 103 | Johnson | 2 | NULL | +---------------+-------------+-------------+-----------+---------------+---------------+
Exemplo de uso de LATERAL com FLATTEN()¶
Este exemplo mostra como uma junção lateral pode utilizar a exibição em linha devolvida por FLATTEN
:
SELECT * FROM table1, LATERAL FLATTEN(...);
Primeiro, atualizar a tabela de funcionários para incluir os dados ARRAY nos quais FLATTEN pode operar:
UPDATE employees SET project_names = ARRAY_CONSTRUCT('Materialized Views', 'UDFs') WHERE employee_ID = 101; UPDATE employees SET project_names = ARRAY_CONSTRUCT('Materialized Views', 'Lateral Joins') WHERE employee_ID = 102;
Segundo, executar uma consulta que utiliza FLATTEN e contém uma referência a uma(s) coluna(s) em uma tabela que a precede:
SELECT emp.employee_ID, emp.last_name, index, value AS project_name FROM employees AS emp, LATERAL FLATTEN(INPUT => emp.project_names) AS proj_names ORDER BY employee_ID; +-------------+-----------+-------+----------------------+ | EMPLOYEE_ID | LAST_NAME | INDEX | PROJECT_NAME | |-------------+-----------+-------+----------------------| | 101 | Richards | 0 | "Materialized Views" | | 101 | Richards | 1 | "UDFs" | | 102 | Paulson | 0 | "Materialized Views" | | 102 | Paulson | 1 | "Lateral Joins" | +-------------+-----------+-------+----------------------+
Exemplos que mostram as duas sintaxes de junção¶
As seguintes instruções SQL são equivalentes e produzem a mesma saída (a saída é mostrada apenas uma vez abaixo). A primeira instrução SQL abaixo usa uma vírgula antes da palavra-chave LATERAL enquanto a segunda instrução SQL usa as palavras-chave INNER JOIN.
SELECT * FROM departments AS d, LATERAL (SELECT * FROM employees AS e WHERE e.department_ID = d.department_ID) AS iv2 ORDER BY employee_ID;SELECT * FROM departments AS d INNER JOIN LATERAL (SELECT * FROM employees AS e WHERE e.department_ID = d.department_ID) AS iv2 ORDER BY employee_ID; +---------------+-------------+-------------+-----------+---------------+---------------+ | DEPARTMENT_ID | NAME | EMPLOYEE_ID | LAST_NAME | DEPARTMENT_ID | PROJECT_NAMES | |---------------+-------------+-------------+-----------+---------------+---------------| | 1 | Engineering | 101 | Richards | 1 | NULL | | 1 | Engineering | 102 | Paulson | 1 | NULL | | 2 | Support | 103 | Johnson | 2 | NULL | +---------------+-------------+-------------+-----------+---------------+---------------+