Я думаю, что я вижу, что вы пытаетесь сделать, и мне интересно, если с помощью interval '5 minutes'
Обильно would't быть лучше и легче следовать подходу:
with times as ( -- find the first date in the dataset, up to today
select
date_trunc ('minutes', min("timestamp")) -
mod (extract ('minutes' from min("timestamp"))::int, 5) * interval '1 minute' as bt,
date_trunc ('minutes', current_timestamp) -
mod (extract ('minutes' from current_timestamp)::int, 5) * interval '1 minute' as et
from hst_energy_d
where
idinstrum = 4 and
id_device = 122
), -- generate every possible range between these dates
ranges as (
select
generate_series(bt, et, interval '5 minutes') as range_start
from times
), -- normalize your data to which 5-minut interval it belongs to
rounded_hst as (
select
date_trunc ('minutes', "timestamp") -
mod (extract ('minutes' from "timestamp")::int, 5) * interval '1 minute' as round_time,
*
from hst_energy_d
where
idinstrum = 4 and
id_device = 122
)
select
r.range_start, r.range_start + interval '5 minutes' as range_end,
avg (hd."Al1")
from
ranges r
left join rounded_hst hd on
r.range_start = hd.round_time
group by
r.range_start
order by
r.range_start
Кстати, проницательный глаз может интересно, зачем беспокоиться о CTE rounded_hst
и почему бы просто не использовать «между» в соединении. Из всего, что я проверил и наблюдал, база данных взорвет все возможности, а затем проверит условие между условиями в том, что составляет предложение where - фильтрованный декартес. Для этого много интервалов, это гарантированно будет убийцей.
Усечение данных до ближайших пяти минут позволяет стандартное соединение SQL. Я призываю вас проверить оба, и я думаю, вы поймете, что я имею в виду.
- EDIT 11/17/2016 -
Решение от OP, который принимает во внимание времена номера, а не даты:
with times as ( -- find the first date in the dataset, up to today
select
date_trunc('minutes', to_timestamp(min("timestamp"))::timestamp) -
mod(extract ('minutes' from to_timestamp(min("timestamp"))::timestamp)::int, 5) * interval '1 minute' as bt,
date_trunc('minutes', current_timestamp::timestamp) -
mod(extract ('minutes' from (current_timestamp)::timestamp)::int, 5) * interval '1 minute' as et
from hst_energy_d
where
idinstrum = 4 and
id_device = 122
), -- generate every possible range between these dates
ranges as (
select
generate_series(bt, et, interval '5 minutes') as range_start
from times
), -- normalize your data to which 5-minute interval it belongs to
rounded_hst as (
select
date_trunc ('minutes', to_timestamp("timestamp")::timestamp)::timestamp -
mod (extract ('minutes' from (to_timestamp("timestamp")::timestamp))::int, 5) * interval '1 minute' as round_time,
*
from hst_energy_d
where
idinstrum = 4 and
id_device = 122
)
select
extract('epoch' from r.range_start)::bigint, extract('epoch' from r.range_start + interval '5 minutes')::bigint as range_end,
avg (hd."Al1")
from
ranges r
left join rounded_hst hd on
r.range_start = hd.round_time
group by
r.range_start
order by
r.range_start;
, что аккуратный запрос! К сожалению, 'timestamp' является' BIGINT' вместо реальной «timestamp», поэтому моя математика с числами вместо timestamps – Bertuz
Я адаптировал ваш предложенный код для работы с bigint, но я не уверен, что это все еще возможно используйте более легкий SQL. [gist to the new SQL] (https://gist.github.com/bertuz/5544663474b8a0850dcede03d1903a02) можете ли вы взглянуть и дать мне несколько отзывов? Плюс: вы говорили о том, что Postgres лучше справляются с вашим решением: как вы анализировали это? Используя 'EXPLAIN'? Вот [запрос плана] (https://gist.github.com/bertuz/5f06ab81cde3e78231c94c3a76ad20f8), который выполняет мой запрос. Действительно ли он выполняет два сканирования по hst_energy_d? Это много*! Спасибо – Bertuz
Хорошо, 'EXPLAIN' говорит сам за себя: ваши решения стоят' 48.47', в мистерах стоит 247.17' – Bertuz