I have a PostgreSQL 9.1 database with a table containing a timestamp and a measuring value
\'2012-10-25 01:00\' 2
\'2012-10-2
The key is to make a virtual table against which to join your results sets. The generate_series
function can help do that, in the following manner:
SELECT
start
, start + interval '8 hours' as end
FROM (
SELECT generate_series(
date'2012-01-01'
, date'2012-02-02'
, '1 hour'
) AS start
) x;
This produces output something like this:
start | end
------------------------+------------------------
2012-01-01 00:00:00+00 | 2012-01-01 08:00:00+00
2012-01-01 01:00:00+00 | 2012-01-01 09:00:00+00
2012-01-01 02:00:00+00 | 2012-01-01 10:00:00+00
2012-01-01 03:00:00+00 | 2012-01-01 11:00:00+00
This gives you something to join your data to. In this way, the following query:
SELECT
y.start
, round(avg(ts_val.v))
FROM
ts_val,
(
SELECT
start
, start + interval '8 hours' as end
FROM (
SELECT generate_series(
date'2012-01-01'
, date'2012-02-02'
, '1 hour'
) AS start
) x
) y
WHERE
ts BETWEEN y.start AND y.end
GROUP BY
y.start
ORDER BY
y.start
;
For the following data
ts | v
---------------------+---
2012-01-01 01:00:00 | 2
2012-01-01 09:00:00 | 2
2012-01-01 10:00:00 | 5
(3 rows)
Will produce the following results:
start | round
------------------------+-------
2012-01-01 00:00:00+00 | 2.0
2012-01-01 01:00:00+00 | 2.0
2012-01-01 02:00:00+00 | 3.5
2012-01-01 03:00:00+00 | 3.5
2012-01-01 04:00:00+00 | 3.5
2012-01-01 05:00:00+00 | 3.5
2012-01-01 06:00:00+00 | 3.5
2012-01-01 07:00:00+00 | 3.5
2012-01-01 08:00:00+00 | 3.5
2012-01-01 09:00:00+00 | 3.5
2012-01-01 10:00:00+00 | 5.0
(11 rows)