sql >> Databasteknik >  >> RDS >> PostgreSQL

Postgres analog till CROSS APPLY i SQL Server

I Postgres 9.3 eller senare använd en LATERAL gå med:

SELECT v.col_a, v.col_b, f.*  -- no parentheses here, f is a table alias
FROM   v_citizenversions v
LEFT   JOIN LATERAL f_citizen_rec_modified(v.col1, v.col2) f ON true
WHERE  f.col_c = _col_c;

Varför LEFT JOIN LATERAL ... ON true ?

  • Post som returneras från funktionen har kolumner sammanlänkade

För äldre versioner , det finns ett mycket enkelt sätt att åstadkomma vad jag tycker du försöker med en set-returnerande funktion (RETURNS TABLE eller RETURNS SETOF record ELLER RETURNS record ):

SELECT *, (f_citizen_rec_modified(col1, col2)).*
FROM   v_citizenversions v

Funktionen beräknar värden en gång för varje rad i den yttre frågan. Om funktionen returnerar flera rader, multipliceras resulterande rader i enlighet med detta. Alla parenteser krävs syntaktiskt för att dekomponera en radtyp. Tabellfunktionen kan se ut ungefär så här:

CREATE OR REPLACE FUNCTION f_citizen_rec_modified(_col1 int, _col2 text)
  RETURNS TABLE(col_c integer, col_d text) AS
$func$
SELECT s.col_c, s.col_d
FROM   some_tbl s
WHERE  s.col_a = $1
AND    s.col_b = $2
$func$ LANGUAGE sql;

Du måste slå in detta i en underfråga eller CTE om du vill använda en WHERE klausul eftersom kolumnerna inte är synliga på samma nivå. (Och det är ändå bättre för prestanda, eftersom du förhindrar upprepad utvärdering för varje utdatakolumn i funktionen):

SELECT col_a, col_b, (f_row).*
FROM (
   SELECT col_a, col_b, f_citizen_rec_modified(col1, col2) AS f_row
   FROM   v_citizenversions v
   ) x
WHERE (f_row).col_c = _col_c;

Det finns flera andra sätt att göra detta eller något liknande. Allt beror på vad du vill ha exakt.



  1. MariaDB CHARACTER_LENGTH() Förklarad

  2. Hur man inaktiverar Change Data Capture (CDC) på en databas i SQL Server - SQL Server Tutorial

  3. Hur man hämtar två kolumndata i A,B-format i Oracle

  4. Oracle-tabellen eller -vyn existerar inte inifrån den lagrade proceduren