PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL generate_series() mit SQL-Funktion als Argumente

Was Sie versuchen, könnte so funktionieren:

Mit zusätzlichen Informationen bearbeiten

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;

Aufruf:

SELECT * FROM f_products_per_month();

Hauptpunkte:

  • Endgültige Bearbeitung, um eine ansonsten leere Zeile für Monate ohne Produkte einzufügen.
  • Du hast "LEFT JOIN" geschrieben, aber so kann es nicht funktionieren.
  • Dafür gibt es mehrere Möglichkeiten, aber RETURN QUERY ist am elegantesten.
  • Verwenden Sie denselben Rückgabetyp wie Ihre Funktion get_forecast_history().
  • Vermeiden Sie Namenskonflikte mit den OUT-Parametern, indem Sie die Spaltennamen tabellarisch qualifizieren (entfällt in der finalen Version).
  • Verwenden Sie DATE '2008-01-01' nicht , verwenden Sie einen Zeitstempel wie ich, er muss sowieso für to_char() konvertiert werden. Weniger Casting, bessere Leistung (nicht, dass es in diesem Fall viel ausmacht).
  • '2008-01-01 0:0'::timestamp und timestamp '2008-01-01 0:0' sind nur zwei Syntaxvarianten, die dasselbe tun.
  • Für ältere Versionen von PostgreSQL ist die Sprache plpgsql standardmäßig nicht installiert. Möglicherweise müssen Sie CREATE LANGUAGE plpgsql; ausführen einmal in Ihrer Datenbank. Siehe das Handbuch hier .

Sie könnten Ihre beiden Funktionen wahrscheinlich zu einer Abfrage oder Funktion vereinfachen, wenn Sie möchten.