Ответ 1
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 time range
AND ts < '2012-09-03 00:00:00+02'::timestamptz -- careful with borders
GROUP BY 1, 2
ORDER BY 1, 2;
CTE t
предоставляет данные, подобные вашей таблице: одна временная метка ts
в минуту с номером bandwidth
. (Вам не нужна эта часть, вместо этого вы работаете со своей таблицей.)
Вот очень похожее решение для очень похожего вопроса - с подробным объяснением того, как работает эта конкретная агрегация:
Вот аналогичное решение для аналогичного вопроса о текущих суммах - с подробным объяснением и ссылками для различных используемых функций:
Дополнительный вопрос в комментарии
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;
Получает один неагрегированный образец за 15-минутный интервал - из последней доступной строки в окне. Это будет 15-я минута, если строка не будет отсутствовать. Ключевыми частями являются DISTINCT ON
и ORDER BY
.
Более подробная информация о используемой технике здесь: