I allmänhet måste du studera grunderna , innan du börjar ställa frågor.
Läs den utmärkta manualen om CREATE FUNCTION
, PL/pgSQL
och SQL-funktioner
.
Huvudpunkter varför exemplet är nonsens
-
För det första kan du inte lämna in en identifierare som du gör. Identifierare kan inte parametriseras i vanlig SQL. Du behöver dynamisk SQL för det.
Naturligtvis behöver du faktiskt inte det, enligt dina krav. Det är bara ett bord inblandat. Det är nonsens att försöka parametrisera det. -
Använd inte typnamn som identifierare. Jag använder
_date
istället fördate
som parameternamn och döpte om din tabellkolumn tillasset_date
.ALTER
din tabelldefinition därefter. -
En funktion som hämtar data från en tabell kan aldrig vara
IMMUTABLE
. Läs manualen. -
Du blandar SQL-syntax med plpgsql-element på orimliga sätt.
WITH
är en del av enSELECT
och kan inte blandas med plpgsql-kontrollstrukturer somLOOP
ellerIF
.
Riktig funktion
En korrekt funktion kan se ut så här (ett av många sätt):
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
Prestanda borde inte vara så dåligt, men det är bara en meningslös komplikation.
Rätt lösning:vanlig fråga
Det enklaste (och förmodligen snabbaste) sättet skulle vara med fönsterfunktionen 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;
Standardavvikelse
Enligt din senare kommentar vill du beräkna statistiska siffror som standardavvikelse.
Det finns dedikerade aggregera funktioner för statistik
i PostgreSQL.