sql >> Base de Datos >  >> RDS >> PostgreSQL

Iterando a través de registros de PostgreSQL. ¿Cómo hacer referencia a los datos de la siguiente fila?

Generalmente necesitas estudiar lo básico , antes de comenzar a hacer preguntas.
Lea el excelente manual sobre CREATE FUNCTION , PL/pgSQL y funciones SQL .

Puntos principales por los que el ejemplo no tiene sentido

  • Primero, no puede entregar un identificador como tu lo haces. Los identificadores no se pueden parametrizar en SQL simple. Necesitaría SQL dinámico para eso.
    Por supuesto, en realidad no necesita eso, de acuerdo con sus requisitos. Solo hay una mesa involucrada. No tiene sentido intentar parametrizarlo.

  • No utilice nombres de tipos como identificadores. Yo uso _date en lugar de date como nombre de parámetro y cambió el nombre de la columna de su tabla a asset_date . ALTER la definición de su tabla en consecuencia.

  • Una función que extrae datos de una tabla nunca puede ser IMMUTABLE . Lea el manual.

  • Está mezclando la sintaxis SQL con elementos plpgsql de manera absurda. WITH es parte de un SELECT instrucción y no se puede mezclar con estructuras de control plpgsql como LOOP o IF .

Funcionamiento adecuado

Una función adecuada podría verse así (una de muchas formas):

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

El rendimiento no debería ser tan malo, pero es una complicación sin sentido.

Solución adecuada:consulta simple

La forma más sencilla (y probablemente la más rápida) sería con la función de ventana 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;

Desviación estándar

Según su comentario posterior, desea calcular números estadísticos como la desviación estándar.
Hay funciones agregadas para estadísticas en PostgreSQL.