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 dedate
comme nom de paramètre et renommé la colonne de votre table enasset_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'unSELECT
et ne peut pas être mélangé avec des structures de contrôle plpgsql commeLOOP
ouIF
.
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.