sql >> Databáze >  >> RDS >> PostgreSQL

Jaký je rozdíl mezi LATERAL JOIN a poddotazem v PostgreSQL?

Co je a LATERAL připojit se?

Tato funkce byla představena s PostgreSQL 9.3. Manuál:

Dílčí dotazy zobrazené v FROM může předcházet klíčové slovoLATERAL . To jim umožňuje odkazovat na sloupce poskytnuté předchozím FROM položky. (Bez LATERAL , je každý poddotaz vyhodnocen nezávisle, a tak nemůže křížově odkazovat na žádný jiný FROM položka.)

Tabulkové funkce zobrazené v FROM může také předcházet klíčové slovo LATERAL , ale pro funkce je klíčové slovo nepovinné; argumenty funkce mohou obsahovat odkazy na sloupce poskytnuté předřazením FROM položky v každém případě.

Jsou zde uvedeny základní příklady kódu.

Spíš jako korelovaný dílčí dotaz

A LATERAL join je spíše jako korelovaný poddotaz, nikoli prostý poddotaz, v tom výrazy napravo od LATERAL join jsou vyhodnoceny jednou pro každý řádek vlevo od něj – stejně jako korelované poddotaz - zatímco prostý poddotaz (tabulkový výraz) je vyhodnocen jednou pouze. (Plánovač dotazů však nabízí způsoby, jak optimalizovat výkon pro oba.)
Související odpověď s příklady kódu pro oba vedle sebe, řešící stejný problém:

  • Optimalizujte dotaz GROUP BY pro načtení posledního řádku na uživatele

Pro vrácení více než jednoho sloupce , LATERAL join je obvykle jednodušší, čistší a rychlejší.
Nezapomeňte také, že ekvivalentem korelovaného dílčího dotazu je LEFT JOIN LATERAL ... ON true :

  • Volejte funkci vracející sadu s argumentem pole vícekrát

Věci, které dílčí dotaz neumí

jsou věci, které LATERAL join umí, ale (související) poddotaz ne (snadno). Korelovaný poddotaz může vrátit pouze jednu hodnotu, nikoli více sloupců a ne více řádků – s výjimkou volání holých funkcí (která znásobí řádky výsledků, pokud vrátí více řádků). Ale i určité funkce vracející sadu jsou povoleny pouze v FROM doložka. Jako unnest() s více parametry v Postgres 9.4 nebo novější. Manuál:

To je povoleno pouze v FROM doložka;

Takže to funguje, ale nelze (snadno) nahradit poddotazem:

CREATE TABLE tbl (a1 int[], a2 int[]);
SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2);  -- implicit LATERAL

Čárka (, ) v FROM klauzule je krátký zápis pro CROSS JOIN .
LATERAL se u tabulkových funkcí předpokládá automaticky.
O speciálním případě UNNEST( array_expression [, ... ] ) :

  • Jak deklarujete, že funkce set-returning- bude povolena pouze v klauzuli FROM?

Nastavte funkce vracení v SELECT seznam

Můžete také použít funkce vracející sadu, jako je unnest() v SELECT vypsat přímo. To se projevovalo překvapivým chováním s více než jednou takovou funkcí ve stejném SELECT seznam až do Postgresu 9.6. Ale konečně byl dezinfikován pomocí Postgres 10 a je nyní platnou alternativou (i když ne standardní SQL). Viz:

  • Jaké je očekávané chování pro více funkcí vracejících sadu v klauzuli SELECT?

Na základě výše uvedeného příkladu:

SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM   tbl;

Srovnání:

dbfiddle pro pg 9.6 zde
dbfiddle pro pg 10 zde

Objasněte dezinformace

Manuál:

Pro INNER a OUTER typu spojení, musí být specifikována podmínka spojení, a to přesně jedna z NATURAL , ON join_condition nebo USING (join_column [, ...]). Význam viz níže.
Pro CROSS JOIN , žádná z těchto klauzulí se nemůže objevit.

Takže tyto dva dotazy jsou platné (i když nejsou nijak zvlášť užitečné):

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;

Zatímco tento není:

SELECT *
FROM   tbl t
LEFT   JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;

To je důvod, proč je příklad kódu Andomar správný (CROSS JOIN nevyžaduje podmínku připojení) a Attilův je nebyl.



  1. Jak najít cestu pg_config

  2. Jak funguje funkce RIGHT() v SQL Server (T-SQL)

  3. Úplné odstranění MySQL 5.7

  4. Úvod do databáze vysoké dostupnosti pro MySQL a MariaDB