下面是一個利用設施將聚合函數用作窗口函數的方法。聚合函數會保留數組中最後15分鐘的觀察值以及當前的運行總數。狀態轉換功能將元素從陣列中移出,落在15分鐘的窗口後面,並推動最近的觀察。最終的功能只是計算陣列中的平均溫度。
現在,至於這是否是一種好處......取決於。它側重於postgresql的plgpsql執行部分,而不是數據庫訪問部分,而我自己的經驗是plpgsql不快。如果您可以輕鬆查找表格以查找每個觀察結果的前15分鐘行,則自行加入(如在@danihp答案中)將會很好。然而,這種方法可以處理來自更復雜的來源的觀察結果,其中這些查找是不實際的。像以往一樣,試用並在自己的系統上進行比較。
-- based on using this table definition
create table observation(id int primary key, timestamps timestamp not null unique,
temperature numeric(5,2) not null);
-- note that I'm reusing the table structure as a type for the state here
create type rollavg_state as (memory observation[], total numeric(5,2));
create function rollavg_func(state rollavg_state, next_in observation) returns rollavg_state immutable language plpgsql as $$
declare
cutoff timestamp;
i int;
updated_memory observation[];
begin
raise debug 'rollavg_func: state=%, next_in=%', state, next_in;
cutoff := next_in.timestamps - '15 minutes'::interval;
i := array_lower(state.memory, 1);
raise debug 'cutoff is %', cutoff;
while i <= array_upper(state.memory, 1) and state.memory[i].timestamps < cutoff loop
raise debug 'shifting %', state.memory[i].timestamps;
i := i + 1;
state.total := state.total - state.memory[i].temperature;
end loop;
state.memory := array_append(state.memory[i:array_upper(state.memory, 1)], next_in);
state.total := coalesce(state.total, 0) + next_in.temperature;
return state;
end
$$;
create function rollavg_output(state rollavg_state) returns float8 immutable language plpgsql as $$
begin
raise debug 'rollavg_output: state=% len=%', state, array_length(state.memory, 1);
if array_length(state.memory, 1) > 0 then
return state.total/array_length(state.memory, 1);
else
return null;
end if;
end
$$;
create aggregate rollavg(observation) (sfunc = rollavg_func, finalfunc = rollavg_output, stype = rollavg_state);
-- referring to just a table name means a tuple value of the row as a whole, whose type is the table type
-- the aggregate relies on inputs arriving in ascending timestamp order
select rollavg(observation) over (order by timestamps) from observation;
如果新的15分鐘窗口啓動,滾動平均值是否會「重新啓動」?還是應該平均計算「最後」15分鐘? –
@a_horse_with_no_name,實際上,數據集包含4周的歷史數據,我需要移動平均結果作爲新的數據集。 –
這不能回答我的問題。 –