PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Regrouper par intervalles de données

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;

Le CTE t fournit des données comme votre table pourrait contenir :un horodatage ts par minute avec une bandwidth Numéro. (Vous n'avez pas besoin de cette partie, vous travaillez avec votre table à la place.)

Voici une solution très similaire pour une question très similaire - avec une explication détaillée du fonctionnement de cette agrégation particulière :

  • date_trunc intervalle de 5 minutes dans PostgreSQL

Voici une solution similaire pour une question similaire concernant la course sommes - avec des explications détaillées et des liens pour les différentes fonctions utilisées :

  • PostgreSQL :nombre de lignes en cours pour une requête "par minute"

Question supplémentaire en commentaire

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;

Récupère un échantillon non agrégé par intervalle de 15 minutes - à partir de la dernière ligne disponible dans la fenêtre. Ce sera la 15e minute si la rangée ne manque pas. Les parties cruciales sont DISTINCT ON et ORDER BY .
Plus d'informations sur la technique utilisée ici :

  • Sélectionner la première ligne de chaque groupe GROUP BY ?