Ответ 1
Больше похоже на коррелированный подзапрос
LATERAL
соединение (Postgres 9.3 или новее) больше похоже на коррелированный подзапрос, а не простой подзапрос. Как указывал Андомар, функция или подзапрос справа от LATERAL
соединения должен оцениваться один раз для каждой строки слева от него - как коррелированный подзапрос - в то время как простой подзапрос (табличное выражение) оценивается только один раз. (Однако у планировщика запросов есть способы оптимизировать производительность для любого из них.)
У этого связанного ответа есть примеры кода для обеих сторон, решая ту же самую проблему:
Для возврата более одного столбца LATERAL
соединение обычно проще, чище и быстрее.
Кроме того, помните, что эквивалентом коррелированного подзапроса является LEFT JOIN LATERAL... ON true
:
Прочтите руководство по LATERAL
Это более авторитетно, чем все, что мы собираемся вставить в ответы здесь:
- https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-LATERAL
- http://www.postgresql.org/docs/current/static/sql-select.html
То, что подзапрос не может сделать
Есть вещи, которые может сделать LATERAL
соединение, но (коррелированный) подзапрос не может (легко). Коррелированный подзапрос может возвращать только одно значение, а не несколько столбцов и не несколько строк, за исключением простых вызовов функций (которые умножают результирующие строки, если они возвращают несколько строк). Но даже некоторые возвращающие множество функции разрешены только в предложении FROM
. Как и unnest()
с несколькими параметрами в Postgres 9.4 или новее. Руководство:
Это разрешено только в предложении
FROM
;
Так что это работает, но не может быть легко заменено подзапросом:
CREATE TABLE tbl (a1 int[], a2 int[]);
SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2); -- implicit LATERAL
Запятая (,
) в предложении FROM
является кратким обозначением для CROSS JOIN
. LATERAL
предполагается автоматически для табличных функций.
Подробнее о специальном случае UNNEST( array_expression [,... ] )
:
Набор возвращающих функций в списке SELECT
Вы также можете использовать функции, возвращающие множество, например, unnest()
в списке SELECT
. Раньше это демонстрировало удивительное поведение с более чем одной такой функцией в одном списке SELECT
до Postgres 9.6. Но он, наконец, был продезинфицирован с помощью Postgres 10 и теперь является допустимой альтернативой (даже если не стандартным SQL). Увидеть:
Опираясь на приведенный выше пример:
SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM tbl;
Сравнение:
dbfiddle для pg 9.6 здесь
dbfiddle для pg 10 здесь
Уточнить дезинформацию
Для типов соединения
INNER
иOUTER
должно быть указано условие соединения, а именно одно из следующих:NATURAL
,ON
join_condition илиUSING
(join_column [,...]). Смотрите ниже значение.
ДляCROSS JOIN
ни одно из этих предложений не может появиться.
Таким образом, эти два запроса действительны (даже если они не особенно полезны):
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;
Пока этого нет
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
Вот почему пример кода @Andomar является правильным (для CROSS JOIN
не требуется условие соединения), а @Attila является недействительным.