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

Iterazione attraverso i record PostgreSQL. Come fare riferimento ai dati dalla riga successiva?

In genere è necessario studiare le basi , prima di iniziare a fare domande.
Leggi l'eccellente manuale su CREATE FUNCTION , PL/pgSQL e Funzioni SQL .

Principali punti per cui l'esempio non ha senso

  • Innanzitutto, non puoi consegnare un identificatore come fai tu. Gli identificatori non possono essere parametrizzati in SQL semplice. Avresti bisogno di SQL dinamico per quello.
    Ovviamente, in realtà non ne hai bisogno, in base alle tue esigenze. C'è solo una tabella coinvolta. Non ha senso provare a parametrizzarlo.

  • Non utilizzare i nomi dei tipi come identificatori. Uso _date invece di date come nome del parametro e rinominato la colonna della tabella in asset_date . ALTER la definizione della tua tabella di conseguenza.

  • Una funzione che recupera i dati da una tabella non può mai essere IMMUTABLE . Leggi il manuale.

  • Stai mescolando la sintassi SQL con elementi plpgsql in modi senza senso. WITH fa parte di un SELECT istruzione e non può essere mescolato con strutture di controllo plpgsql come LOOP o IF .

Funzione corretta

Una funzione corretta potrebbe assomigliare a questa (uno dei tanti modi):

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

Le prestazioni non dovrebbero essere così male, ma è solo una complicazione inutile.

Soluzione corretta:query semplice

Il modo più semplice (e probabilmente più veloce) sarebbe con la funzione finestra 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;

Deviazione standard

Secondo il tuo commento successivo, vuoi calcolare numeri statistici come la deviazione standard.
Ci sono aggrega le funzioni per le statistiche in PostgreSQL.