ここでは、ファンクションを使用して集計関数をウィンドウ関数として使用するアプローチがあります。集計関数は、アレイ内の最後の15分間の観測値を、現在の実行中の合計とともに保持します。状態遷移関数は、15分のウィンドウの後ろにある配列から要素をシフトし、最新の観測をプッシュします。最終的な関数は単純に配列の平均温度を計算します。
これが利益であるかどうかに関しては、それは依存しています。これはデータベースアクセス部分ではなくpostgresqlのplgpsql実行部分に焦点を当てています。私の経験ではplpgsqlは高速ではありません。あなたが簡単にテーブルに戻って各観測の前の15分の行を見つけることができれば、自己結合(@danihp答えのように)がうまくいくでしょう。しかし、このアプローチは、よりルックアップが実用的でない、より複雑なソースからの観察に対処することができます。これまでどおり、自分のシステムで試用して比較します。
あなたは各15分間隔の後にローリング平均を再開したいと仮定すると、
-- 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週間の履歴データが含まれており、移動平均結果を新しいデータセットとして必要とします。 –
それは私の質問に答えることはありません。 –