52

測定データを次の構造に保存しています。

CREATE TABLE measurements(
measured_at TIMESTAMPTZ,
val INTEGER
);

私はすでにそれを使用していることを知っています

(a)date_trunc('hour',measured_at)

(ロ)generate_series

次の方法でデータを集計できます。

microseconds,
milliseconds
.
.
.

しかし、データを 5 分または任意の秒単位で集計することは可能ですか? 測定データを任意の秒数で集計することはできますか?

可能性のある季節性を確認するために、さまざまな時間分解能で集計されたデータを FFT または AR モデルにフィードする必要があります。

4

10 に答える 10

57

generate_series() によって作成された間隔を追加することで、「バケット」のテーブルを生成できます。この SQL ステートメントは、データの初日 ( の値min(measured_at)) の 5 分間バケットのテーブルを生成します。

select 
  (select min(measured_at)::date from measurements) + ( n    || ' minutes')::interval start_time,
  (select min(measured_at)::date from measurements) + ((n+5) || ' minutes')::interval end_time
from generate_series(0, (24*60), 5) n

そのステートメントを共通テーブル式でラップすると、ベース テーブルであるかのように結合およびグループ化できます。

with five_min_intervals as (
  select 
    (select min(measured_at)::date from measurements) + ( n    || ' minutes')::interval start_time,
    (select min(measured_at)::date from measurements) + ((n+5) || ' minutes')::interval end_time
  from generate_series(0, (24*60), 5) n
)
select f.start_time, f.end_time, avg(m.val) avg_val 
from measurements m
right join five_min_intervals f 
        on m.measured_at >= f.start_time and m.measured_at < f.end_time
group by f.start_time, f.end_time
order by f.start_time

任意の秒数によるグループ化も同様です --use date_trunc()


generate_series() をより一般的に使用すると、5 分のバケットの上限を推測する必要がなくなります。実際には、これをビューまたは関数として構築することになるでしょう。ベース テーブルを使用すると、パフォーマンスが向上する場合があります。

select 
  (select min(measured_at)::date from measurements) + ( n    || ' minutes')::interval start_time,
  (select min(measured_at)::date from measurements) + ((n+5) || ' minutes')::interval end_time
from generate_series(0, ((select max(measured_at)::date - min(measured_at)::date from measurements) + 1)*24*60, 5) n;
于 2012-08-20T22:59:50.527 に答える
16

Catcall には素晴らしい答えがあります。それを使用する私の例は、固定バケットを持つことを示しています。この場合、真夜中から始まる 30 分間隔です。また、Catcall の最初のバージョンで 1 つの余分なバケットが生成される可能性があることと、それを削除する方法も示しています。1日にちょうど48個のバケツが欲しかった. 私の問題では、観測には別々の日付と時刻の列があり、さまざまなサービスについて、月全体で 30 分間の観測を平均したいと考えています。

with intervals as (
    select
        (n||' minutes')::interval as start_time, 
        ((n+30)|| ' minutes')::interval as end_time
    from generate_series(0, (23*60+30), 30) n
)
select i.start_time, o.service, avg(o.o)
from
observations o right join intervals i
on o.time >= i.start_time and o.time < i.end_time
where o.date between '2013-01-01' and '2013-01-31'
group by i.start_time, i.end_time, o.service
order by i.start_time
于 2013-02-23T09:28:17.567 に答える
10

次の例では、適切な分/時間/任意の境界に一致しない場合でも、任意のサイズのバケットを取得できます。値「300」は 5 分間のグループ化用ですが、任意の値に置き換えることができます。

select measured_at, 
       val, 
       (date_trunc('seconds', (measured_at - timestamptz 'epoch') / 300) * 300 + timestamptz 'epoch') as aligned_measured_at
from measurements;

次に、「val」の周りに必要な集計を使用し、必要に応じて「aligned_measured_at によるグループ化」を使用できます。

于 2015-11-02T23:52:37.743 に答える
2

おそらく、あなたはextract(epoch from measured_at)それから行くことができますか?

于 2012-08-20T21:45:34.467 に答える