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
etimestamp '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.