sql >> Database >  >> RDS >> PostgreSQL

Wat is het verschil tussen LATERAL JOIN en een subquery in PostgreSQL?

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.



  1. Grote objecten mogen niet worden gebruikt in de modus voor automatisch vastleggen

  2. Vraag laatste N gerelateerde rijen per rij op

  3. Hoe de RTRIM()-functie werkt in MySQL

  4. Database versus tabelruimte, wat is het verschil?