sql >> Database teknologi >  >> RDS >> PostgreSQL

Hvordan beregner man et eksponentielt glidende gennemsnit på postgres?

Du kan definere din egen aggregerede funktion og derefter bruge den med en vinduesspecifikation for at få det samlede output på hvert trin i stedet for en enkelt værdi.

Så et aggregat er et stykke tilstand og en transformationsfunktion til at ændre denne tilstand for hver række, og eventuelt en afsluttende funktion til at konvertere tilstanden til en outputværdi. For et simpelt tilfælde som dette burde blot en transformationsfunktion være tilstrækkelig.

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);

hvilket giver 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

Disse tal ser ud til at svare til det regneark, du føjede til spørgsmålet.

Du kan også definere funktionen til at sende alfa som en parameter fra sætningen:

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

Desuden er denne funktion faktisk så enkel, at den slet ikke behøver at være i plpgsql, men kan kun være en sql-funktion, selvom du ikke kan henvise til parametre ved navn i en af ​​disse:

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. MariaDB LOCALTIMESTAMP() Forklaret

  2. Opdater ListView baseret på SQLite-understøttet ContentProvider

  3. SQL Server 2014:Native backup-kryptering

  4. Sådan afbrydes udførelsen af ​​en erklæring i PostgreSQL