sql >> Database >  >> RDS >> PostgreSQL

Itereren door PostgreSQL-records. Hoe verwijzen naar gegevens van de volgende rij?

Over het algemeen moet je de basis bestuderen , voordat je vragen gaat stellen.
Lees de uitstekende handleiding over CREATE FUNCTION , PL/pgSQL en SQL-functies .

Belangrijkste punten waarom het voorbeeld onzin is

  • Ten eerste mag je geen identifier . inleveren zoals jij doet. Identifiers kunnen niet worden geparametriseerd in gewone SQL. Je hebt nodig dynamische SQL daarvoor.
    Natuurlijk heb je dat niet echt nodig, volgens jouw eisen. Er is maar één tafel bij betrokken. Het is onzin om het te proberen te parametriseren.

  • Gebruik geen typenamen als identifiers. Ik gebruik _date in plaats van date als parameternaam en hernoemde uw tabelkolom naar asset_date . ALTER uw tabeldefinitie dienovereenkomstig.

  • Een functie die gegevens uit een tabel haalt, kan nooit IMMUTABLE zijn . Lees de handleiding.

  • U vermengt de SQL-syntaxis met plpgsql-elementen op onzinnige manieren. WITH maakt deel uit van een SELECT statement en kan niet worden gemengd met plpgsql-besturingsstructuren zoals LOOP of IF .

Juiste functie

Een goede functie kan er als volgt uitzien (een van de vele manieren):

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

Prestaties zouden niet zo slecht moeten zijn, maar het is gewoon een zinloze complicatie.

Goede oplossing:gewone vraag

De eenvoudigste (en waarschijnlijk snelste) manier zou zijn met de vensterfunctie 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;

Standaarddeviatie

Volgens je latere opmerking wil je statistische getallen zoals standaarddeviatie berekenen.
Er zijn speciale aggregeer functies voor statistieken in PostgreSQL.



  1. echo iets uit MySQL-database

  2. Combineer INSERT en SELECT in één SQL-query (Zapier)

  3. Fatale fout tijdens het uitvoeren van een opdracht MySQL VB

  4. Haal de uitvoeringstijd van het sql-script op in oracle sqlplus