2016-11-16 11 views
2

これは、great answerからインスパイアされました。前年の5分間隔で計算されたAVGを返す次のクエリを書きました。グループ化されていないデータを挿入する方法

すべての5分間隔がで、場合によっては特定のタイムスパンに一致する行がない場合はnullに設定します。

with intervals as (select 
        (select min("timestamp") from public.hst_energy_d) + n AS start_timestamp, 
        (select min("timestamp") from public.hst_energy_d) + n + 299 AS end_timestamp 
        from generate_series(extract(epoch from now())::BIGINT - 10596096000, extract(epoch from now())::BIGINT, 300) n) 
(SELECT AVG(meas."Al1") as "avg", islots.start_timestamp AS "timestamp" 
FROM public.hst_energy_d meas 
    RIGHT OUTER JOIN intervals islots 
    on meas.timestamp >= islots.start_timestamp and meas.timestamp <= islots.end_timestamp 
WHERE 
    meas.idinstrum = 4 
    AND 
    meas.id_device = 122 
    AND 
    meas.timestamp > extract(epoch from now()) - 10596096000 
GROUP BY islots.start_timestamp, islots.end_timestamp 
ORDER BY timestamp); 

答えて

1

私は私はあなたが何をしようとして見ると思うし、自由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; 
+0

何きちんと問い合わせ!残念なことに 'timestamp'は本当の' timestamp'の代わりに 'BIGINT'ですので、タイムスタンプの代わりに数値を使った数値計算 – Bertuz

+0

bigintを使うために提案したコードを修正しましたが、より軽いSQLを活用してください。 [新しいSQLの要点](https://gist.github.com/bertuz/5544663474b8a0850dcede03d1903a02)どうぞご覧ください。プラス:あなたのソリューションでパフォーマンスが向上したPostgresについて話しました。どのように分析しましたか? 'EXPLAIN'を使って?ここでは、私のクエリが実行する[クエリプラン](https://gist.github.com/bertuz/5f06ab81cde3e78231c94c3a76ad20f8)です。それは実際にhst_energy_dで2回のスキャンを実行していますか?それは多いです*!ありがとうございました – Bertuz

+0

申し訳ありませんが、 'EXPLAIN'が自ら語ります。あなたのソリューションコストは' 48.47'、鉱山コストは '247.17'です。 – Bertuz

関連する問題