sql >> Base de Datos >  >> RDS >> PostgreSQL

Postgres análogo a CROSS APPLY en SQL Server

En Postgres 9.3 o posterior use un LATERAL unirse:

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;

Por qué LEFT JOIN LATERAL ... ON true ?

  • El registro devuelto por la función tiene columnas concatenadas

Para versiones anteriores , hay una forma muy sencilla de lograr lo que creo está intentando hacerlo con una función de devolución de conjuntos (RETURNS TABLE o RETURNS SETOF record O RETURNS record ):

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

La función calcula los valores una vez para cada fila de la consulta externa. Si la función devuelve varias filas, las filas resultantes se multiplican en consecuencia. Todos los paréntesis son requeridos sintácticamente para descomponer un tipo de fila. La función de tabla podría verse así:

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;

Debe envolver esto en una subconsulta o CTE si desea aplicar un WHERE cláusula porque las columnas no son visibles en el mismo nivel. (Y es mejor para el rendimiento de todos modos, porque evita la evaluación repetida para cada columna de salida de la función):

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;

Hay varias otras formas de hacer esto o algo similar. Todo depende de lo que quieras exactamente.