PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

PostgreSQL generate_series() avec la fonction SQL comme arguments

Ce que vous essayez de faire pourrait fonctionner comme ceci :

Modifier avec des informations supplémentaires

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;

Appel :

SELECT * FROM f_products_per_month();

Points majeurs :

  • Modification finale pour inclure une ligne autrement vide pendant des mois sans produits.
  • Vous avez écrit "LEFT JOIN", mais ce n'est pas ainsi que cela peut fonctionner.
  • Il existe plusieurs façons de procéder, mais RETURN QUERY est le plus élégant.
  • Utilisez le même type de retour que celui utilisé par votre fonction get_forecast_history().
  • Évitez les conflits de nommage avec les paramètres OUT en qualifiant de table les noms de colonne (ne s'applique plus dans la version finale).
  • N'utilisez pas DATE '2008-01-01' , utilisez un horodatage comme je l'ai fait, il doit être converti pour to_char() de toute façon. Moins de casting, plus performant (ce n'est pas si important dans ce cas).
  • '2008-01-01 0:0'::timestamp et timestamp '2008-01-01 0:0' ne sont que deux variantes de syntaxe faisant la même chose.
  • Pour les anciennes versions de PostgreSQL, le langage plpgsql n'est pas installé par défaut. Vous devrez peut-être émettre CREATE LANGUAGE plpgsql; une fois dans votre base de données. Voir le manuel ici .

Vous pourriez probablement simplifier vos deux fonctions en une seule requête ou fonction si vous le souhaitez.