私は私はあなたが何をしようとして見ると思うし、自由interval '5 minutes'
を使用してのアプローチに従う方が良いと容易になりwould't場合、私は疑問に思う:5月ところで
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結合が可能です。私は両方をテストすることをお勧めします、私はあなたが私が意味するものを見ると思います。
- EDIT 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)どうぞご覧ください。プラス:あなたのソリューションでパフォーマンスが向上したPostgresについて話しました。どのように分析しましたか? 'EXPLAIN'を使って?ここでは、私のクエリが実行する[クエリプラン](https://gist.github.com/bertuz/5f06ab81cde3e78231c94c3a76ad20f8)です。それは実際にhst_energy_dで2回のスキャンを実行していますか?それは多いです*!ありがとうございました – Bertuz
申し訳ありませんが、 'EXPLAIN'が自ら語ります。あなたのソリューションコストは' 48.47'、鉱山コストは '247.17'です。 – Bertuz