С тех пор, как Postgres получил возможность выполнять LATERAL
объединения, я уже читал об этом, поскольку в настоящее время я делаю сложные дампы данных для своей команды с большим количеством неэффективных подзапросов, которые делают общий запрос продолжительностью четыре минуты или более.
Я понимаю , что LATERAL
присоединяется может быть в состоянии помочь мне, но даже после прочтения статьи как это одно из кучного Analytics, я до сих пор не совсем понимаю.
Какой вариант использования для LATERAL
объединения? В чем разница между LATERAL
объединением и подзапросом?
sql
postgresql
subquery
lateral-join
jdotjdot
источник
источник
apply
совпадаетlateral
со стандартом SQL)Ответы:
Больше похоже на коррелированный подзапрос
LATERAL
Присоединиться (Postgres 9.3 или более поздней версии) больше похож на коррелированных подзапросов , а не простой подзапроса. Как указывал Андомар , функция или подзапрос справа отLATERAL
объединения должен оцениваться один раз для каждой строки слева от него - так же, как коррелированный подзапрос - в то время как простой подзапрос (табличное выражение) оценивается только один раз . (Однако в планировщике запросов есть способы оптимизировать производительность для любого из них.)Этот связанный ответ содержит примеры кода для обеих сторон, решая одну и ту же проблему:
Для возвращения более одного столбца ,
LATERAL
присоединиться , как правило , проще, чище и быстрее.Также помните, что эквивалент коррелированного подзапроса
LEFT JOIN LATERAL ... ON true
:Прочтите руководство на
LATERAL
Это более авторитетно, чем все, что мы собираемся вставить в ответы здесь:
То, что подзапрос не может сделать
Там являются вещи , которые
LATERAL
присоединяются можно сделать, но (коррелируют) подзапрос не может (легко). Коррелированный подзапрос может возвращать только одно значение, а не несколько столбцов и не несколько строк, за исключением простых вызовов функций (которые умножают результирующие строки, если они возвращают несколько строк). Но даже некоторые функции, возвращающие множество, разрешены только вFROM
предложении. Как и в случаеunnest()
с несколькими параметрами в Postgres 9.4 или новее. Руководство:Так что это работает, но не может быть легко заменено подзапросом:
Запятая (
,
) вFROM
предложении является кратким обозначением дляCROSS JOIN
.LATERAL
предполагается автоматически для табличных функций.Подробнее о частном случае
UNNEST( array_expression [, ... ] )
:Набор возвращающих функций в
SELECT
спискеВы также можете использовать функции, возвращающие множество, как
unnest()
вSELECT
списке напрямую. Раньше это демонстрировало удивительное поведение с более чем одной такой функцией в одном и том жеSELECT
списке до Postgres 9.6. Но он, наконец, был продезинфицирован с помощью Postgres 10 и теперь является допустимой альтернативой (даже если не стандартным SQL). Видеть:Опираясь на приведенный выше пример:
Сравнение:
dbfiddle для pg 9.6 здесь
dbfiddle для pg 10 здесь
Уточнить дезинформацию
Руководство:
Таким образом, эти два запроса действительны (даже если они не особенно полезны):
Пока этого нет
Вот почему @ Andomar в примере кода является правильным (
CROSS JOIN
не требует условие соединения) и @ АттилыISбыл недействителен.источник
LATERAL
подзапросе: gis.stackexchange.com/a/230070/7244Разница между не-
lateral
иlateral
объединением заключается в том, можете ли вы посмотреть на строку левой таблицы. Например:Этот «внешний вид» означает, что подзапрос должен оцениваться более одного раза. Ведь
t1.col1
можно принять много значений.В отличие от этого подзапрос после
lateral
неприсоединения может быть оценен один раз:Как и требуется
lateral
, внутренний запрос никак не зависит от внешнего запроса.lateral
Запрос является примеромcorrelated
запроса, из - за его связи с рядами за пределами самого запроса.источник
select * from table1 left join t2 using (col1)
сравнивать? Мне непонятно, когда соединение с использованием / on является недостаточным, и было бы более целесообразно использовать боковое.Во-первых, боковое и поперечное применение - это одно и то же . Поэтому вы также можете прочитать о Cross Apply. Поскольку он был внедрен в SQL Server целую вечность, вы найдете больше информации о нем, чем Lateral.
Во-вторых, согласно моему пониманию , вы ничего не можете сделать, используя подзапрос вместо использования бокового. Но:
Рассмотрим следующий запрос.
Вы можете использовать боковой в этом состоянии.
В этом запросе вы не можете использовать обычное объединение из-за предложения limit. Боковое или поперечное применение может использоваться, когда нет простого условия соединения .
Существует более широкое применение для бокового или поперечного применения, но это наиболее распространенный вариант, который я нашел.
источник
lateral
вместоapply
. Возможно, Microsoft запатентовала синтаксис?lateral
в стандарте SQL, ноapply
это не так.LEFT JOIN
Требует условие соединения. Сделайте это,ON TRUE
если вы не хотите как-то ограничивать.cross join
илиon
условиеОдна вещь, на которую никто не указал, состоит в том, что вы можете использовать
LATERAL
запросы для применения определенной пользователем функции к каждой выбранной строке.Например:
Это единственный способ, которым я знаю, как делать подобные вещи в PostgreSQL.
источник