आप अपने स्वयं के समग्र कार्य को परिभाषित कर सकते हैं और फिर एक एकल मान के बजाय प्रत्येक चरण में कुल आउटपुट प्राप्त करने के लिए विंडो विनिर्देश के साथ इसका उपयोग कर सकते हैं।
तो एक समुच्चय राज्य का एक टुकड़ा है, और प्रत्येक पंक्ति के लिए उस स्थिति को संशोधित करने के लिए एक परिवर्तन कार्य है, और वैकल्पिक रूप से राज्य को आउटपुट मान में बदलने के लिए एक अंतिम कार्य है। इस तरह के एक साधारण मामले के लिए, बस एक ट्रांसफ़ॉर्म फ़ंक्शन पर्याप्त होना चाहिए।
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);
जो मुझे देता है:
[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
ऐसा लगता है कि ये संख्याएं उस स्प्रैडशीट से मेल खाती हैं जिसे आपने प्रश्न में जोड़ा था।
साथ ही, आप कथन से एक पैरामीटर के रूप में अल्फा पास करने के लिए फ़ंक्शन को परिभाषित कर सकते हैं:
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
साथ ही, यह फ़ंक्शन वास्तव में इतना सरल है कि इसे plpgsql में होने की आवश्यकता नहीं है, लेकिन यह केवल एक sql फ़ंक्शन हो सकता है, हालांकि आप उनमें से किसी एक में नाम से पैरामीटर का उल्लेख नहीं कर सकते हैं:
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
$$;