PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL generate_series() con la funzione SQL come argomenti

Quello che stai cercando di fare potrebbe funzionare in questo modo:

Modifica con informazioni aggiuntive

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;

Chiama:

SELECT * FROM f_products_per_month();

Punti principali:

  • Modifica finale per includere una riga altrimenti vuota per mesi senza prodotti.
  • Hai scritto "LEFT JOIN", ma non è così che può funzionare.
  • Ci sono diversi modi per farlo, ma RETURN QUERY è il più elegante.
  • Utilizza lo stesso tipo di ritorno utilizzato dalla tua funzione get_forecast_history().
  • Evita i conflitti di denominazione con i parametri OUT qualificando come tabella i nomi delle colonne (non più applicabili nella versione finale).
  • Non utilizzare DATE '2008-01-01' , usa un timestamp come ho fatto io, deve comunque essere convertito per to_char(). Meno casting, prestazioni migliori (non che importi molto in questo caso).
  • '2008-01-01 0:0'::timestamp e timestamp '2008-01-01 0:0' sono solo due varianti di sintassi che fanno lo stesso.
  • Per le versioni precedenti di PostgreSQL il linguaggio plpgsql non è installato di default. Potrebbe essere necessario emettere CREATE LANGUAGE plpgsql; una volta nel tuo database. Vedi il manuale qui .

Probabilmente potresti semplificare le tue due funzioni in una query o funzione, se lo desideri.