PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Postgres análogo ao CROSS APPLY no SQL Server


No Postgres 9.3 ou mais tarde, use um LATERAL Junte-se:
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 que LEFT JOIN LATERAL ... ON true ?
  • O registro retornado da função tem colunas concatenadas

Para versões mais antigas , há uma maneira muito simples de realizar o que eu acho você está tentando com uma função de retorno de conjunto (RETURNS TABLE ou RETURNS SETOF record OU RETURNS record ):
SELECT *, (f_citizen_rec_modified(col1, col2)).*
FROM   v_citizenversions v

A função calcula valores uma vez para cada linha da consulta externa. Se a função retornar várias linhas, as linhas resultantes serão multiplicadas de acordo. Todos os parênteses são sintaticamente obrigatórios para decompor um tipo de linha. A função da tabela pode ser algo assim:
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;

Você precisa envolver isso em uma subconsulta ou CTE se quiser aplicar um WHERE cláusula porque as colunas não são visíveis no mesmo nível. (E é melhor para o desempenho de qualquer maneira, porque você evita avaliações repetidas para cada coluna de saída da função):
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;

Existem várias outras maneiras de fazer isso ou algo semelhante. Tudo depende do que você quer exatamente.