2016-12-01 17 views
4

日付は月の最終日であるテーブルに毎月の時系列データがあります。一部の日付がデータにありません。私はそれらの日付を挿入し、他の属性の値をゼロにします。次のように 表は以下のとおりです。私はPostgresqlのtimeseriesデータに不足している月の日付を追加する

id  report_date price 
1  2015-01-31 40 
1  2015-02-28 56 
1  2015-03-31 0 
1  2015-04-30 34 
2  2014-05-31 45 
2  2014-06-30 0 
2  2014-07-31 0 
2  2014-08-31 47 

にこのテーブルを変換したい

id  report_date price 
1  2015-01-31 40 
1  2015-02-28 56 
1  2015-04-30 34 
2  2014-05-31 45 
2  2014-08-31 47 

たちはPostgreSQLでこれを行うことができます方法はありますか? 現在、Pythonでこれを行っています。私たちのデータは日々増えており、1つのタスクだけでI/Oを処理するのは効率的ではありません。

はありがとう

答えて

1
あなたは日付を生成し、その後、 left join値をもたらすこと generate_series()を使ってこれを行うことができます

with m as (
     select id, min(report_date) as minrd, max(report_date) as maxrd 
     from t 
     group by id 
    ) 
select m.id, m.report_date, coalesce(t.price, 0) as price 
from (select m.*, generate_series(minrd, maxrd, interval '1' month) as report_date 
     from m 
    ) m left join 
    t 
    on m.report_date = t.report_date; 

EDIT:

上記にはないことが判明月の最後に月を追加しても、月の最後の日が保持されないため、かなり機能します。

これは、簡単に固定されている:

with t as (
     select 1 as id, date '2012-01-31' as report_date, 10 as price union all 
     select 1 as id, date '2012-04-30', 20 
    ), m as (
     select id, min(report_date) - interval '1 day' as minrd, max(report_date) - interval '1 day' as maxrd 
     from t 
     group by id 
    ) 
select m.id, m.report_date, coalesce(t.price, 0) as price 
from (select m.*, generate_series(minrd, maxrd, interval '1' month) + interval '1 day' as report_date 
     from m 
    ) m left join 
    t 
    on m.report_date = t.report_date; 

最初のCTEは単なるサンプルデータを生成することです。

+0

あなたGordenをありがとう! これは私のために働いた – liferacer

0

これは、Gordonのクエリより若干改善されており、場合によっては月の最後の日付を取得できません。

基本的に、あなたは0価格で行方不明の日付を表示するには、この生成されたテーブルの上にminmaxgenerate_seriesを使用して)各IDの日付とleft join間のすべての月の終了日を生成します。

with minmax as (
     select id, min(report_date) as mindt, max(report_date) as maxdt 
     from t 
     group by id 
    ) 
select m.id, m.report_date, coalesce(t.price, 0) as price 
from (select *, 
     generate_series(date_trunc('MONTH',mindt+interval '1' day), 
         date_trunc('MONTH',maxdt+interval '1' day), 
         interval '1' month) - interval '1 day' as report_date 
     from minmax 
    ) m 
left join t on m.report_date = t.report_date 

Sample Demo

関連する問題