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

PostgreSQL generar_series () con la función SQL como argumentos

Lo que está tratando de hacer podría funcionar así:

Editar con información adicional

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;

Llamar:

SELECT * FROM f_products_per_month();

Puntos principales:

  • Edición final para incluir una fila vacía para meses sin productos.
  • Escribiste "LEFT JOIN", pero no es así como puede funcionar.
  • Hay varias formas de hacer esto, pero RETURN QUERY es el más elegante.
  • Use el mismo tipo de devolución que usa su función get_forecast_history().
  • Evite los conflictos de nombres con los parámetros OUT calificando los nombres de las columnas en tablas (ya no se aplica en la versión final).
  • No use DATE '2008-01-01' , use una marca de tiempo como lo hice yo, tiene que convertirse para to_char() de todos modos. Menos lanzamiento, funciona mejor (no es que importe mucho en este caso).
  • '2008-01-01 0:0'::timestamp y timestamp '2008-01-01 0:0' son solo dos variantes de sintaxis que hacen lo mismo.
  • Para versiones anteriores de PostgreSQL, el lenguaje plpgsql no está instalado de forma predeterminada. Es posible que deba ejecutar CREATE LANGUAGE plpgsql; una vez en su base de datos. Consulte el manual aquí .

Si lo desea, probablemente podría simplificar sus dos funciones en una consulta o función.