Wat is a LATERAL
meedoen?
De functie is geïntroduceerd met PostgreSQL 9.3. De handleiding:
Subquery's die verschijnen in FROM
kan worden voorafgegaan door het sleutelwoordLATERAL
. Hierdoor kunnen ze verwijzen naar kolommen die zijn geleverd door de vorige FROM
artikelen. (Zonder LATERAL
, elke subquery wordt onafhankelijk geëvalueerd en kan dus niet verwijzen naar een andere FROM
item.)
Tabelfuncties die verschijnen in FROM
kan ook worden voorafgegaan door het trefwoord LATERAL
, maar voor functies is het sleutelwoord optioneel; de argumenten van de functie kunnen verwijzingen bevatten naar kolommen die voorafgaan aan FROM
items in ieder geval.
Daar worden basiscodevoorbeelden gegeven.
Meer als een gecorreleerde subquery
Een LATERAL
join lijkt meer op een gecorreleerde subquery, niet op een gewone subquery, in die zin dat expressies rechts van een LATERAL
join worden één keer geëvalueerd voor elke rij links ervan - net als een gecorreleerde subquery - terwijl een gewone subquery (tabeluitdrukking) eenmaal wordt geëvalueerd enkel en alleen. (De queryplanner heeft echter manieren om de prestaties voor beide te optimaliseren.)
Gerelateerd antwoord met codevoorbeelden voor beide naast elkaar, waarmee hetzelfde probleem wordt opgelost:
- Optimaliseer de GROUP BY-query om de laatste rij per gebruiker op te halen
Voor het retourneren van meer dan één kolom , een LATERAL
join is doorgaans eenvoudiger, schoner en sneller.
Onthoud ook dat het equivalent van een gecorreleerde subquery LEFT JOIN LATERAL ... ON true
is :
- Een set-retournerende functie met een array-argument meerdere keren aanroepen
Dingen die een subquery niet kan doen
Er zijn zijn dingen die een LATERAL
join kan doen, maar een (gecorreleerde) subquery niet (gemakkelijk). Een gecorreleerde subquery kan slechts één waarde retourneren, niet meerdere kolommen en niet meerdere rijen - met uitzondering van kale functieaanroepen (die resultaatrijen vermenigvuldigen als ze meerdere rijen retourneren). Maar zelfs bepaalde set-return-functies zijn alleen toegestaan in de FROM
clausule. Zoals unnest()
met meerdere parameters in Postgres 9.4 of hoger. De handleiding:
Dit is alleen toegestaan in de FROM
clausule;
Dit werkt dus, maar kan niet (gemakkelijk) worden vervangen door een subquery:
CREATE TABLE tbl (a1 int[], a2 int[]);
SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2); -- implicit LATERAL
De komma (,
) in de FROM
clausule is een korte notatie voor CROSS JOIN
.LATERAL
wordt automatisch aangenomen voor tabelfuncties.
Over het speciale geval van UNNEST( array_expression [, ... ] )
:
- Hoe verklaar je dat een set-returning-functie alleen is toegestaan in de FROM-component?
Set-returning functies in de SELECT
lijst
Je kunt ook set-returning-functies gebruiken, zoals unnest()
in de SELECT
lijst direct. Dit vertoonde vroeger verrassend gedrag met meer dan één dergelijke functie in dezelfde SELECT
lijst tot Postgres 9.6. Maar het is eindelijk opgeschoond met Postgres 10 en is nu een geldig alternatief (zelfs als het geen standaard SQL is). Zie:
- Wat is het verwachte gedrag voor functies die meerdere sets retourneren in de SELECT-component?
Voortbouwend op bovenstaand voorbeeld:
SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM tbl;
Vergelijking:
dbfiddle voor pg 9.6 hier
dbfiddle voor pg 10 hier
Verduidelijk verkeerde informatie
De handleiding:
Voor de INNER
en OUTER
join-types, er moet een join-voorwaarde worden opgegeven, namelijk precies een van NATURAL
, ON
join_condition ,of USING
(join_column [, ...]). Zie hieronder voor de betekenis.
Voor CROSS JOIN
, kan geen van deze clausules verschijnen.
Dus deze twee zoekopdrachten zijn geldig (zelfs als ze niet bijzonder nuttig zijn):
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;
Hoewel deze niet:
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
Daarom is het codevoorbeeld van Andomar correct (de CROSS JOIN
vereist geen lidmaatschapsvoorwaarde) en Attila's is was niet.