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

Agrupar por intervalos de datos

WITH t AS (
   SELECT ts, (random()*100)::int AS bandwidth
   FROM   generate_series('2012-09-01', '2012-09-04', '1 minute'::interval) ts
   )

SELECT date_trunc('hour', ts) AS hour_stump
      ,(extract(minute FROM ts)::int / 15) AS min15_slot
      ,count(*) AS rows_in_timeslice               -- optional
      ,sum(bandwidth) AS sum_bandwidth
FROM   t
WHERE  ts >= '2012-09-02 00:00:00+02'::timestamptz -- user's time range
AND    ts <  '2012-09-03 00:00:00+02'::timestamptz -- careful with borders 
GROUP  BY 1, 2
ORDER  BY 1, 2;

El CTE t proporciona datos como los que podría contener su tabla:una marca de tiempo ts por minuto con un bandwidth número. (No necesita esa parte, en su lugar trabaja con su mesa).

Aquí hay una solución muy similar para una pregunta muy similar, con una explicación detallada de cómo funciona esta agregación en particular:

  • date_trunc intervalo de 5 minutos en PostgreSQL

Aquí hay una solución similar para una pregunta similar sobre ejecutar sumas:con una explicación detallada y enlaces para las diversas funciones utilizadas:

  • PostgreSQL:conteo continuo de filas para una consulta 'por minuto'

Pregunta adicional en comentario

WITH -- same as above ...

SELECT DISTINCT ON (1,2)
       date_trunc('hour', ts) AS hour_stump
      ,(extract(minute FROM ts)::int / 15) AS min15_slot
      ,bandwidth AS bandwith_sample_at_min15
FROM   t
WHERE  ts >= '2012-09-02 00:00:00+02'::timestamptz
AND    ts <  '2012-09-03 00:00:00+02'::timestamptz
ORDER  BY 1, 2, ts DESC;

Recupera uno muestra no agregada por intervalo de 15 minutos - desde la última fila disponible en la ventana. Este será el minuto 15 si no falta la fila. Las partes cruciales son DISTINCT ON y ORDER BY .
Más información sobre la técnica utilizada aquí:

  • ¿Seleccionar la primera fila en cada grupo GROUP BY?