나는 당신이 뭘 하려는지 볼 생각과 접근 방식에 따라하기 더 쉬울 would't 자유롭게 interval '5 minutes'
를 사용하는 경우 궁금 : 분별의 눈은 수도 그런데
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 절에 해당하는 조건 (즉, 필터링 된 데카르트 식)을 테스트합니다. 이 많은 간격 동안, 그것은 살인자가 될 것입니다.
각 데이터를 가장 가까운 5 분으로 잘라내어 표준 SQL 조인을 허용합니다. 나는 둘 다 테스트 해보길 바란다. 나는 당신이 내가 의미하는 것을 보게 될 것이라고 생각한다.
- 편집 2016년 11월 17일 - 고려 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'는 진짜'timestamp' 대신에'BIGINT'입니다. 그러므로 타임 스탬프 대신 숫자를 사용한 수학 – Bertuz
bigint를 사용하기 위해 제안 된 코드를 수정했습니다. 그러나 이것이 여전히 가능할 지 확신하지 못합니다 더 가벼운 SQL을 활용하십시오. [새로운 SQL 개요] (https://gist.github.com/bertuz/5544663474b8a0850dcede03d1903a02) 한 번 둘러 보시고 피드백을 주시겠습니까? Plus : 솔루션으로 Postgres 성능을 향상시키는 방법에 대해 이야기했습니다. 어떻게 분석 했습니까? 'EXPLAIN'을 사용하여? 여기 내 쿼리가 수행하는 [쿼리 계획] (https://gist.github.com/bertuz/5f06ab81cde3e78231c94c3a76ad20f8)입니다. 실제로 hst_energy_d에서 두 번의 스캔을 수행합니까? 그게 * 많은 *! 감사합니다 – Bertuz
좋아요,'EXPLAIN'은 자체적으로 말합니다 : 귀하의 솔루션 비용은'48.47'이고, 내 비용은'247.17'입니다. – Bertuz