根据丢失的时间范围自动填充数据库中的丢失行

时间:2019-07-31 01:40:44

标签: python sql postgresql

我在Postgresql数据库中有一个表,该表存储日期时间以及一些看起来像这样的整数:

      dt                total                                                   
--------------------------------                                        
2019-07-01 10:00:00     150                                      
2019-07-01 10:15:00     153                                      
2019-07-01 10:30:00     155                                      
2019-07-01 10:45:00     160                                      
2019-07-01 11:00:00     161                                   
....

您会看到dt列中的日期时间将连续15分钟。我的问题是,有时输入数据可能会丢失某些行。

例如:

     dt                total                                                   
--------------------------------                                        
2019-07-01 10:00:00     150                                      
2019-07-01 10:15:00     153                                      
2019-07-01 10:30:00     155                                      
2019-07-01 10:45:00     160                                      
2019-07-01 11:00:00     161
2019-07-01 11:15:00     163
2019-07-01 12:00:00     170

在此示例中,有n = 2个丢失的行,分别为时间11:30和11:45。我要在此处执行的操作是自动填充这些行的日期时间,并使用缺少行前(11:15)的最后一行的总列和丢失行后(12:00)的第一行的平均值作为每个丢失项的总数行

在此示例中,每个缺少的行的总列将相加(170-163)/(n + 1)= 7/3 = 2.333(在此使用3个十进制数字),结果将如下所示:< / p>

     dt                total                                                   
--------------------------------                                        
2019-07-01 10:00:00     150                                      
2019-07-01 10:15:00     153                                      
2019-07-01 10:30:00     155                                      
2019-07-01 10:45:00     160                                      
2019-07-01 11:00:00     161
2019-07-01 11:15:00     163
2019-07-01 11:30:00     165.333
2019-07-01 11:45:00     167.666
2019-07-01 12:00:00     170

我认为这不能直接用SQL完成。因此,我认为Python可能有助于解决此问题。有想法吗?

1 个答案:

答案 0 :(得分:2)

您可以使用generate_series()和一些数学运算。以下假设total在增加(如您的示例数据中所示):

select d.dt, seqnum,
       coalesce(t.total,
                (max(t.total) over (order by d.dt asc) +
                 (min(t.total) over (order by d.dt desc) - 
                  max(t.total) over (order by d.dt asc)
                 ) *
                 (seqnum - max(seqnum) filter (where t.total is not null) over (order by d.dt asc)) /
                  nullif(min(seqnum) filter (where t.total is not null) over (order by d.dt desc) -
                         max(seqnum) filter (where t.total is not null) over (order by d.dt asc),
                         0
                        )
                 )
                )
from (select dt, count(*) over (order by dt) as seqnum
      from (select generate_series(min(dt), max(dt), interval '15 minute') as dt
            from t
            ) d
     ) d left join
     t
     on t.dt = d.dt;

Here是db <>小提琴。

计算很麻烦,因为您需要进行加权平均值才能获得中间值。公式是:

prev_value + (next_value - previous_value) * ratio

与比率为:

(current_time - prev_time) / (next_time - prev_time)

但是,它不是使用时间,而是使用顺序计数。