Você pode gerar uma tabela de "buckets" adicionando intervalos criados por generate_series(). Essa instrução SQL gerará uma tabela de buckets de cinco minutos para o primeiro dia (o valor de
min(measured_at)
) em seus dados. 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
Enrole isso declaração em uma expressão de tabela comum, e você pode unir e agrupar nela como se fosse uma tabela base.
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
O agrupamento por um número arbitrário de segundos é semelhante -- use
date_trunc()
. Um uso mais geral de generate_series() permite evitar adivinhar o limite superior para buckets de cinco minutos. Na prática, você provavelmente construiria isso como uma visão ou uma função. Você pode obter melhor desempenho de uma tabela base.
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;