Anda dapat menentukan fungsi agregat Anda sendiri dan kemudian menggunakannya dengan spesifikasi jendela untuk mendapatkan output agregat pada setiap tahap daripada nilai tunggal.
Jadi agregat adalah bagian dari keadaan, dan fungsi transformasi untuk mengubah keadaan itu untuk setiap baris, dan secara opsional fungsi finalisasi untuk mengubah keadaan menjadi nilai keluaran. Untuk kasus sederhana seperti ini, fungsi transformasi saja sudah cukup.
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);
yang memberi saya:
[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
Angka-angka ini tampaknya cocok dengan spreadsheet yang Anda tambahkan ke pertanyaan.
Selain itu, Anda dapat mendefinisikan fungsi untuk meneruskan alfa sebagai parameter dari pernyataan:
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
Selain itu, fungsi ini sebenarnya sangat sederhana sehingga tidak perlu berada di plpgsql sama sekali, tetapi dapat berupa fungsi sql saja, meskipun Anda tidak dapat merujuk ke parameter dengan nama di salah satunya:
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
$$;