PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Postgres analogo a CROSS APPLY in SQL Server

In Postgres 9.3 o in seguito usa un LATERAL unisciti:

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;

Perché LEFT JOIN LATERAL ... ON true ?

  • Il record restituito dalla funzione ha colonne concatenate

Per versioni precedenti , esiste un modo molto semplice per realizzare ciò che penso stai provando con una funzione di restituzione di set (RETURNS TABLE o RETURNS SETOF record OPPURE RETURNS record ):

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

La funzione calcola i valori una volta per ogni riga della query esterna. Se la funzione restituisce più righe, le righe risultanti vengono moltiplicate di conseguenza. Tutte le parentesi sono sintatticamente obbligatori per scomporre un tipo di riga. La funzione tabella potrebbe assomigliare a questa:

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;

È necessario racchiuderlo in una sottoquery o CTE se si desidera applicare un WHERE clausola perché le colonne non sono visibili allo stesso livello. (E comunque è meglio per le prestazioni, perché impedisci la valutazione ripetuta per ogni colonna di output della funzione):

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;

Ci sono molti altri modi per farlo o qualcosa di simile. Tutto dipende da cosa vuoi esattamente.