Більше схожий на співвіднесений підзапитів
LATERAL
Приєднатися (Postgres 9.3 або більш пізньої версії) більше схожий на корелюється підзапитів , а не простий підзапиту. Як зазначав Андомар , функцію або підзапит праворуч від LATERAL
об'єднання потрібно оцінювати один раз для кожного рядка, що залишився від нього - як і співвіднесений підзапит - в той час як простий підзапит (вираження таблиці) оцінюється лише один раз . (Планувальник запитів, однак, має способи оптимізації продуктивності для будь-якого.)
Ця відповідна відповідь має приклади коду для обох поряд, вирішуючи ту саму проблему:
Для повернення декількох стовпців , LATERAL
з'єднання, як правило, простіше, чистіше та швидше.
Також пам’ятайте, що еквівалент корельованого підпиту LEFT JOIN LATERAL ... ON true
:
Прочитайте посібник на LATERAL
Це більш авторитетно, ніж усе, що ми збираємось тут відповісти:
Те, що підзапит не може зробити
Є деякі речі, які 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
не вимагає умова з'єднання) і @ Аттіли IS був недійсний.
apply
є такий же , якlateral
від стандарту SQL)