sql >> Base de Datos >  >> RDS >> PostgreSQL

Postgresql SQL GROUP BY intervalo de tiempo con precisión arbitraria (hasta milisegundos)

Puede generar una tabla de "cubos" agregando intervalos creados por generate_series(). Esta instrucción SQL generará una tabla de intervalos de cinco minutos para el primer día (el valor de min(measured_at) ) en sus datos.

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

Envuelve eso declaración en una expresión de tabla común, y puede unirse y agruparse en ella como si fuera una tabla 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

La agrupación por un número arbitrario de segundos es similar:use date_trunc() .

Un uso más general de generate_series() le permite evitar adivinar el límite superior para depósitos de cinco minutos. En la práctica, probablemente construiría esto como una vista o una función. Puede obtener un mejor rendimiento de una tabla 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;