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

Itérer dans les enregistrements PostgreSQL. Comment référencer les données de la ligne suivante ?

Généralement, vous devez étudier les bases , avant de commencer à poser des questions.
Lisez l'excellent manuel sur CREATE FUNCTION , PL/pgSQL et fonctions SQL .

Points majeurs pour lesquels l'exemple est absurde

  • Tout d'abord, vous ne pouvez pas remettre un identifiant comme vous le faites. Les identificateurs ne peuvent pas être paramétrés en SQL brut. Vous auriez besoin de SQL dynamique pour cela.
    Bien sûr, vous n'en avez pas vraiment besoin, selon vos besoins. Il n'y a qu'une seule table impliquée. C'est un non-sens d'essayer de le paramétrer.

  • N'utilisez pas de noms de type comme identificateurs. J'utilise _date au lieu de date comme nom de paramètre et renommé la colonne de votre table en asset_date . ALTER votre définition de table en conséquence.

  • Une fonction récupérant des données d'une table ne peut jamais être IMMUTABLE . Lire le manuel.

  • Vous mélangez la syntaxe SQL avec des éléments plpgsql de manière absurde. WITH fait partie d'un SELECT et ne peut pas être mélangé avec des structures de contrôle plpgsql comme LOOP ou IF .

Fonction correcte

Une fonction appropriée pourrait ressembler à ceci (de plusieurs manières) :

CREATE FUNCTION percentage_change_func(_asset_symbol text)
  RETURNS TABLE(asset_date date, price numeric, pct_change numeric) AS
$func$
DECLARE
   last_price numeric;
BEGIN

FOR asset_date, price IN
   SELECT a.asset_date, a.price
   FROM   asset_histories a
   WHERE  a.asset_symbol = _asset_symbol 
   ORDER  BY a.asset_date  -- traverse ascending
LOOP
   pct_change := price / last_price; -- NULL if last_price is NULL
   RETURN NEXT;
   last_price := price;
END LOOP;

END
$func$ LANGUAGE plpgsql STABLE

Les performances ne devraient pas être si mauvaises, mais c'est juste une complication inutile.

Solution appropriée :requête simple

Le moyen le plus simple (et probablement le plus rapide) serait avec la fonction de fenêtre lag() :

SELECT asset_date, price
      ,price / lag(price) OVER (ORDER BY asset_date) AS pct_change
FROM   asset_histories
WHERE  asset_symbol = _asset_symbol 
ORDER  BY asset_date;

Écart type

Selon votre commentaire ultérieur, vous souhaitez calculer des nombres statistiques comme l'écart type.
Il existe des fonctions d'agrégation pour les statistiques dans PostgreSQL.