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

PostgreSQL generate_series() com a função SQL como argumentos


O que você está tentando fazer pode funcionar assim:

Editar com informações adicionais

CREATE OR REPLACE FUNCTION f_products_per_month()
  RETURNS SETOF fcholder AS
$BODY$
DECLARE
    r fcholder;
BEGIN

FOR r.y, r.m IN
    SELECT to_char(x, 'YYYY')::int4  -- AS y
          ,to_char(x, 'MM')::int4    -- AS m
    FROM  (SELECT '2008-01-01 0:0'::timestamp
        + (interval '1 month' * generate_series(0,57)) AS x) x
LOOP
    RETURN QUERY
    SELECT *    -- use '*' in this case to stay in sync
    FROM   get_forecast_history(r.m, r.y);

    IF NOT FOUND THEN
       RETURN NEXT r;
    END IF;
END LOOP;

END;
$BODY$
  LANGUAGE plpgsql;

Ligar:
SELECT * FROM f_products_per_month();

Pontos principais:

  • Edição final para incluir uma linha vazia durante meses sem produtos.
  • Você escreveu "LEFT JOIN", mas não é assim que funciona.
  • Há várias maneiras de fazer isso, mas RETURN QUERY é o mais elegante.
  • Use o mesmo tipo de retorno que sua função get_forecast_history() usa.
  • Evite conflitos de nomenclatura com os parâmetros OUT, qualificando em tabela os nomes das colunas (não se aplica mais na versão final).
  • Não use DATE '2008-01-01' , use um timestamp como eu fiz, ele precisa ser convertido para to_char() de qualquer maneira. Menos elenco, desempenho melhor (não que isso importe muito neste caso).
  • '2008-01-01 0:0'::timestamp e timestamp '2008-01-01 0:0' são apenas duas variantes de sintaxe fazendo o mesmo.
  • Para versões mais antigas do PostgreSQL, a linguagem plpgsql não é instalada por padrão. Você pode ter que emitir CREATE LANGUAGE plpgsql; uma vez em seu banco de dados. Consulte o manual aqui .

Você provavelmente poderia simplificar suas duas funções em uma consulta ou função, se quisesse.