sql >> Database >  >> RDS >> PostgreSQL

Hoe bereken je een exponentieel voortschrijdend gemiddelde op postgres?

U kunt uw eigen aggregatiefunctie definiëren en deze vervolgens gebruiken met een vensterspecificatie om de geaggregeerde uitvoer in elke fase te krijgen in plaats van een enkele waarde.

Dus een aggregaat is een stuk toestand, en een transformatiefunctie om die toestand voor elke rij te wijzigen, en optioneel een finaliseringsfunctie om de toestand om te zetten in een uitvoerwaarde. Voor een eenvoudig geval als dit zou een transformatiefunctie voldoende moeten zijn.

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

wat mij geeft:

[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

Deze getallen lijken overeen te komen met de spreadsheet die je aan de vraag hebt toegevoegd.

U kunt ook de functie definiëren om alpha door te geven als een parameter uit de instructie:

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

Deze functie is ook zo eenvoudig dat het helemaal niet in plpgsql hoeft te zijn, maar gewoon een sql-functie kan zijn, hoewel je in een van deze niet met naam naar parameters kunt verwijzen:

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. Pas op waar u op let

  2. Oracle SQL GROUP BY geen GROUP BY-expressie help

  3. door komma's gescheiden reeks van geselecteerde waarden in mysql

  4. Updaten van MYSQL naar MYSQLI