2016-12-01 75 views
4

我在表中的月份時間序列數據中,日期是月份的最後一天。數據中缺少一些日期。我想插入這些日期併爲其他屬性設置零值。 表如下:在Postgresql的時間序列數據中添加缺少的每月日期

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 

我想這個錶轉換爲

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 

有什麼辦法,我們可以在PostgreSQL做到這一點? 目前我們正在用Python做這件事。由於我們的數據每天都在增長,並且僅僅爲了一項任務而無法處理I/O。

謝謝

回答

1

可以使用generate_series()生成日期,然後left join中的值帶來做到這一點:

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; 

編輯:

原來那上面沒有相當有效,因爲在月末增加月份並不能保持月份的最後一天。

這很容易固定:

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

謝謝戈登! 這對我有用 – liferacer

0

這是對Gordon的查詢的輕微改進,它在某些情況下未能獲取一個月的最後日期。

基本上你生成minmax日期之間的所有月份結束日期爲每個ID(使用generate_series)和left join在此生成的表顯示丟失的日期與0價格。

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