Supponendo che abbiamo le seguenti tabelle:
create temporary table _data (ref_date date, value int);
insert into _data values
('2016-01-01', 34)
, ('2016-01-02', 12)
, ('2016-01-03', 25)
, ('2016-01-04', 17)
, ('2016-01-05', 22)
;
create temporary table _weight (days_in_past int, weight int);
insert into _weight values
(0, 4)
, (1, 2)
, (2, 1)
;
Poi, se vogliamo calcolare una media mobile su una finestra di tre giorni (compresa la data corrente) in cui i valori più vicini alla data attuale sono assegnato un peso maggiore di quelli più in passato, ci aspettiamo per la media ponderata per 2016-01-05
(basata su valori da 2016-01-05
, 2016-01-04
e 2016-01-03
):
(22*4 + 17*2 + 25*1)/(4+2+1) = 147/7 = 21
e la query potrebbe apparire come segue:
with _prepare_window as (
select
t1.ref_date
, datediff(day, t2.ref_date, t1.ref_date) as days_in_past
, t2.value * weight as weighted_value
, weight
, count(t2.ref_date) over(partition by t1.ref_date rows between unbounded preceding and unbounded following) as num_values_in_window
from
_data t1
left join
_data t2 on datediff(day, t2.ref_date, t1.ref_date) between 0 and 2
left join
_weight on datediff(day, t2.ref_date, t1.ref_date) = days_in_past
order by
t1.ref_date
, datediff(day, t2.ref_date, t1.ref_date)
)
select
ref_date
, round(sum(weighted_value)::float/sum(weight), 0) as weighted_average
from
_prepare_window
where
num_values_in_window = 3
group by
ref_date
order by
ref_date
;
Dare il risultato:
ref_date | weighted_average
------------+------------------
2016-01-03 | 23
2016-01-04 | 19
2016-01-05 | 21
(3 rows)
hai riusciti a trovare una soluzione nel frattempo? – thpl