PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Postgresql SQL GROUP BY Zeitintervall mit beliebiger Genauigkeit (bis auf Millisekunden)

Sie können eine Tabelle mit "Buckets" generieren, indem Sie Intervalle hinzufügen, die von generate_series() erstellt wurden. Diese SQL-Anweisung generiert eine Tabelle mit Fünf-Minuten-Buckets für den ersten Tag (der Wert von min(measured_at) ) in Ihren Daten.

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

Wickeln Sie das ein -Anweisung in einem allgemeinen Tabellenausdruck, und Sie können sie verknüpfen und gruppieren, als wäre es eine Basistabelle.

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

Das Gruppieren nach einer beliebigen Anzahl von Sekunden ist ähnlich – verwenden Sie date_trunc() .

Eine allgemeinere Verwendung von generate_series() lässt Sie vermeiden, die Obergrenze für Fünf-Minuten-Buckets zu erraten. In der Praxis würden Sie dies wahrscheinlich als Ansicht oder Funktion erstellen. Möglicherweise erzielen Sie mit einer Basistabelle eine bessere Leistung.

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;