generate_series() によって作成された間隔を追加することで、「バケット」のテーブルを生成できます。この SQL ステートメントは、データの初日 ( の値min(measured_at)
) の 5 分間バケットのテーブルを生成します。
select
(select min(measured_at)::date from measurements) + ( n || ' minutes')::interval start_time,
(select min(measured_at)::date from measurements) + ((n+5) || ' minutes')::interval end_time
from generate_series(0, (24*60), 5) n
そのステートメントを共通テーブル式でラップすると、ベース テーブルであるかのように結合およびグループ化できます。
with five_min_intervals as (
select
(select min(measured_at)::date from measurements) + ( n || ' minutes')::interval start_time,
(select min(measured_at)::date from measurements) + ((n+5) || ' minutes')::interval end_time
from generate_series(0, (24*60), 5) n
)
select f.start_time, f.end_time, avg(m.val) avg_val
from measurements m
right join five_min_intervals f
on m.measured_at >= f.start_time and m.measured_at < f.end_time
group by f.start_time, f.end_time
order by f.start_time
任意の秒数によるグループ化も同様です --use date_trunc()
。
generate_series() をより一般的に使用すると、5 分のバケットの上限を推測する必要がなくなります。実際には、これをビューまたは関数として構築することになるでしょう。ベース テーブルを使用すると、パフォーマンスが向上する場合があります。
select
(select min(measured_at)::date from measurements) + ( n || ' minutes')::interval start_time,
(select min(measured_at)::date from measurements) + ((n+5) || ' minutes')::interval end_time
from generate_series(0, ((select max(measured_at)::date - min(measured_at)::date from measurements) + 1)*24*60, 5) n;