PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Durch PostgreSQL-Datensätze iterieren. Wie verweise ich auf Daten aus der nächsten Zeile?

Im Allgemeinen müssen Sie die Grundlagen lernen , bevor Sie anfangen, Fragen zu stellen.
Lesen Sie das exzellente Handbuch zu CREATE FUNCTION , PL/pgSQL und SQL-Funktionen .

Wichtige Punkte, warum das Beispiel Unsinn ist

  • Erstens können Sie keine Kennung abgeben so wie du es tust. Bezeichner können in einfachem SQL nicht parametrisiert werden. Sie benötigen dynamisches SQL dafür.
    Natürlich brauchen Sie das nach Ihren Anforderungen eigentlich nicht. Es ist nur eine Tabelle beteiligt. Es ist Unsinn zu versuchen und es zu parametrisieren.

  • Verwenden Sie keine Typnamen als Bezeichner. Ich verwende _date statt date als Parametername und benannte Ihre Tabellenspalte in asset_date um . ALTER Ihre Tabellendefinition entsprechend.

  • Eine Funktion, die Daten aus einer Tabelle holt, kann niemals IMMUTABLE sein . Lesen Sie das Handbuch.

  • Sie mischen SQL-Syntax mit plpgsql-Elementen auf unsinnige Weise. WITH ist Teil eines SELECT -Anweisung und kann nicht mit plpgsql-Kontrollstrukturen wie LOOP gemischt werden oder IF .

Einwandfreie Funktion

Eine richtige Funktion könnte so aussehen (eine von vielen Möglichkeiten):

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

Die Leistung sollte nicht so schlecht sein, aber es ist nur eine sinnlose Komplikation.

Richtige Lösung:einfache Abfrage

Der einfachste (und wahrscheinlich schnellste) Weg wäre mit der Fensterfunktion 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;

Standardabweichung

Gemäß Ihrem späteren Kommentar möchten Sie statistische Zahlen wie die Standardabweichung berechnen.
Es gibt spezielle Aggregatfunktionen für Statistiken in PostgreSQL.