sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur beräknar man ett exponentiellt glidande medelvärde på postgres?

Du kan definiera din egen aggregatfunktion och sedan använda den med en fönsterspecifikation för att få aggregatutdata i varje steg snarare än ett enstaka värde.

Så ett aggregat är en del av tillståndet, och en transformationsfunktion för att modifiera det tillståndet för varje rad, och valfritt en avslutande funktion för att konvertera tillståndet till ett utdatavärde. För ett enkelt fall som detta borde bara en transformationsfunktion vara tillräcklig.

create function ema_func(numeric, numeric) returns numeric
  language plpgsql as $$
declare
  alpha numeric := 0.5;
begin
  -- uncomment the following line to see what the parameters mean
  -- raise info 'ema_func: % %', $1, $2;
  return case
              when $1 is null then $2
              else alpha * $2 + (1 - alpha) * $1
         end;
end
$$;
create aggregate ema(basetype = numeric, sfunc = ema_func, stype = numeric);

vilket ger mig:

[email protected]@[local] =# select x, ema(x, 0.1) over(w), ema(x, 0.2) over(w) from data window w as (order by n asc) limit 5;
     x     |      ema      |      ema      
-----------+---------------+---------------
 44.988564 |     44.988564 |     44.988564
   39.5634 |    44.4460476 |    43.9035312
 38.605724 |   43.86201524 |   42.84396976
 38.209646 |  43.296778316 |  41.917105008
 44.541264 | 43.4212268844 | 42.4419368064

Dessa siffror verkar stämma överens med kalkylarket du lade till i frågan.

Du kan också definiera funktionen för att skicka alfa som en parameter från satsen:

create or replace function ema_func(state numeric, inval numeric, alpha numeric)
  returns numeric
  language plpgsql as $$
begin
  return case
         when state is null then inval
         else alpha * inval + (1-alpha) * state
         end;
end
$$;

create aggregate ema(numeric, numeric) (sfunc = ema_func, stype = numeric);

select x, ema(x, 0.5 /* alpha */) over (order by n asc) from data

Dessutom är den här funktionen faktiskt så enkel att den inte alls behöver vara i plpgsql, utan kan bara vara en sql-funktion, även om du inte kan referera till parametrar med namn i en av dessa:

create or replace function ema_func(state numeric, inval numeric, alpha numeric)
  returns numeric
  language sql as $$
select case
       when $1 is null then $2
       else $3 * $2 + (1-$3) * $1
       end
$$;


  1. Fel relaterat till only_full_group_by vid körning av en fråga i MySql

  2. Vilka är omkostnaderna för att använda AUTOINCREMENT för SQLite på Android?

  3. Fulltextsökning i Postgres eller CouchDB?

  4. Transformera ODBC-data i CloverDX