PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Iterando através de registros PostgreSQL. Como referenciar dados da próxima linha?


Geralmente você precisa estudar o básico , antes de começar a fazer perguntas.
Leia o excelente manual sobre CREATE FUNCTION , PL/pgSQL e funções SQL .

Principais pontos porque o exemplo é absurdo


  • Primeiro, você não pode entregar um identificador como você faz. Os identificadores não podem ser parametrizados em SQL simples. Você precisaria de SQL dinâmico para isso.
    Na verdade, você não precisa disso, de acordo com suas necessidades. Há apenas uma mesa envolvida. É um absurdo tentar parametrizá-lo.

  • Não use nomes de tipo como identificadores. Eu uso _date em vez de date como nome do parâmetro e renomeou sua coluna de tabela para asset_date . ALTER sua definição de tabela de acordo.

  • Uma função que busca dados de uma tabela nunca pode ser IMMUTABLE . Leia o manual.

  • Você está misturando a sintaxe SQL com elementos plpgsql de maneiras sem sentido. WITH faz parte de um SELECT instrução e não pode ser misturado com estruturas de controle plpgsql como LOOP ou IF .

Função adequada


Uma função adequada pode ser assim (uma de muitas maneiras):
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

O desempenho não deveria ser tão ruim, mas é apenas uma complicação inútil.

Solução adequada:consulta simples


A maneira mais simples (e provavelmente mais rápida) seria com a função window 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;

Desvio padrão


De acordo com seu comentário posterior, você deseja calcular números estatísticos como desvio padrão.
funções de agregação para estatísticas no PostgreSQL.