PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Postgresql SQL GROUP BY intervallo di tempo con precisione arbitraria (fino a milli secondi)

Puoi generare una tabella di "bucket" aggiungendo intervalli creati da generate_series(). Questa istruzione SQL genererà una tabella di bucket di cinque minuti per il primo giorno (il valore di min(measured_at) ) nei tuoi dati.

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

Avvolgi quello istruzione in un'espressione di tabella comune e puoi unirti e raggruppare su di essa come se fosse una tabella di 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

Il raggruppamento per un numero arbitrario di secondi è simile:usa date_trunc() .

Un uso più generale di generate_series() ti consente di evitare di indovinare il limite superiore per i bucket di cinque minuti. In pratica, probabilmente lo costruiresti come una vista o una funzione. Potresti ottenere prestazioni migliori da una tabella di 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;