sql >> Databasteknik >  >> RDS >> PostgreSQL

Vad är skillnaden mellan LATERAL JOIN och en underfråga i PostgreSQL?

Vad är en SIDA gå med?

Funktionen introducerades med PostgreSQL 9.3. Manualen:

Undersökningar som visas i FROM kan föregås av nyckelordetSIDA . Detta gör att de kan referera till kolumner som tillhandahålls genom att föregå FRÅN föremål. (Utan SIDA , varje underfråga utvärderas oberoende och kan därför inte korsrefera någon annan FRÅN objekt.)

Tabellfunktioner som visas i FRÅN kan också föregås av nyckelordet LATERAL , men för funktioner är nyckelordet valfritt; Funktionens argument kan innehålla referenser till kolumner som tillhandahålls av FRÅN föremål i alla fall.

Grundläggande kodexempel ges där.

Mer som en korrelerad underfråga

En SIDA join liknar mer en korrelerad underfråga, inte en vanlig underfråga, eftersom uttrycken till höger om en LATERAL join utvärderas en gång för varje rad kvar av den - precis som en korrelerad subquery - medan en vanlig subquery (tabelluttryck) utvärderas en gång endast. (Frågeplaneraren har dock sätt att optimera prestanda för båda.)
Relaterat svar med kodexempel för båda sida vid sida, vilket löser samma problem:

  • Optimera GROUP BY-frågan för att hämta den senaste raden per användare

För att returnera mer än en kolumn , en SIDA join är vanligtvis enklare, renare och snabbare.
Kom också ihåg att motsvarigheten till en korrelerad underfråga är LEFT JOIN LATERAL ... ON true :

  • Anropa en setreturerande funktion med ett matrisargument flera gånger

Saker en underfråga inte kan göra

Det finns saker som en SIDA join kan göra, men en (korrelerad) underfråga kan inte (lätt). En korrelerad underfråga kan bara returnera ett enstaka värde, inte flera kolumner och inte flera rader - med undantag för nakna funktionsanrop (som multiplicerar resultatrader om de returnerar flera rader). Men även vissa set-returnerande funktioner är endast tillåtna i FROM klausul. Som unnest() med flera parametrar i Postgres 9.4 eller senare. Manualen:

Detta är endast tillåtet i FROM klausul;

Så detta fungerar, men kan inte (lätt) ersättas med en underfråga:

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

Kommat (, ) i FRÅN sats är kort notation för CROSS JOIN .
SIDA antas automatiskt för tabellfunktioner.
Om specialfallet UNNEST( array_expression [, ... ] ) :

  • Hur förklarar man att en set-returner-funktion endast är tillåten i FROM-satsen?

Ställ in återvändande funktioner i SELECT lista

Du kan också använda setreturnerande funktioner som unnest() i SELECT lista direkt. Detta brukade uppvisa överraskande beteende med mer än en sådan funktion i samma SELECT lista upp till Postgres 9.6. Men det har äntligen sanerats med Postgres 10 och är ett giltigt alternativ nu (även om det inte är standard SQL). Se:

  • Vad är det förväntade beteendet för flera set-returfunktioner i SELECT-satsen?

Bygger på ovanstående exempel:

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

Jämförelse:

dbfiddle för sid 9.6 här
dbfiddle för sid 10 här

Förtydliga felaktig information

Manualen:

För INNER och YTTER kopplingstyper måste ett kopplingsvillkor anges, nämligen exakt ett av NATURAL , join_condition , eller USING (join_column [, ...]). Se nedan för innebörden.
För KORS-JOIN , ingen av dessa klausuler kan visas.

Så dessa två frågor är giltiga (även om de inte är särskilt användbara):

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;

Även om den här inte är:

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

Det är därför Andomars kodexempel är korrekt (CROSS JOIN kräver inget anslutningsvillkor) och Attilas är var inte.



  1. PHP-array till postgres-array

  2. Hur man duplicerar en databas med phpMyAdmin

  3. Cloud Vendor Deep-Dive:PostgreSQL på Microsoft Azure

  4. Hur tar man bort från select i MySQL?