Group by data intervals
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_bandwidthFROM tWHERE ts >= '2012-09-02 00:00:00+02'::timestamptz -- user's time rangeAND ts < '2012-09-03 00:00:00+02'::timestamptz -- careful with borders GROUP BY 1, 2ORDER BY 1, 2;
The CTE t
provides data like your table might hold: one timestamp ts
per minute with a bandwidth
number. (You don't need that part, you work with your table instead.)
Here is a very similar solution for a very similar question - with detailed explanation how this particular aggregation works:
Here is a similar solution for a similar question concerning running sums - with detailed explanation and links for the various functions used:
Additional question in comment
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_min15FROM tWHERE ts >= '2012-09-02 00:00:00+02'::timestamptzAND ts < '2012-09-03 00:00:00+02'::timestamptzORDER BY 1, 2, ts DESC;
Retrieves one un-aggregated sample per 15 minute interval - from the last available row in the window. This will be the 15th minute if the row is not missing. Crucial parts are DISTINCT ON
and ORDER BY
.
More information about the used technique here:
select date_trunc('hour', d) + (((extract(minute from d)::integer / 5 * 5)::text) || ' minute')::interval as "from", date_trunc('hour', d) + ((((extract(minute from d)::integer / 5 + 1) * 5)::text) || ' minute')::interval - '1 second'::interval as "to", sum(random() * 1000) as bandwidthfrom generate_series('2012-01-01', '2012-01-31', '1 minute'::interval) s(d)group by 1, 2order by 1, 2;
That for 5 minutes ranges. For 15 minutes divide by 15.