用重复和&计算时间序列的增量缺失值

时间:2013-03-14 12:30:06

标签: sql oracle time-series

我有一个Oracle表,它包含logtime / value1,value2 ...的元组,以及其他列,例如计量点id。这些值是不同计数器的采样值,每个计数器都是单调递增的,即较新的值不能小于较旧的值。但是,对于多个采样,值可以保持相等,并且值有时可能会丢失,因此相应的表条目为NULL,而相同logtime的其他值有效。此外,日志时间之间的间隔不是恒定的。

在下文中,为简单起见,我将仅考虑logtime和一个计数器值。

我必须计算从每个logtime到前一个logtime的增量。使用另一个问题here中描述的方法为每个NULL值提供两个NULL增量,因为两个减法无效。当连续值相同时,第二个解决方案失败,因为与先前值的差异被计算两次。

另一种解决方案是构造派生表/视图,将这些NULL值替换为最新的旧有效值。我的方法看起来像这样:

SELECT A.logtime, A.val,
(A.val - (SELECT MAX(C.val) 
          FROM tab C 
          WHERE logtime = 
             (SELECT MAX(B.logtime) 
              FROM tab B 
              WHERE B.logtime < A.logtime AND B.val IS NOT NULL))) AS delta
FROM tab A;

我怀疑这会导致查询效率非常低,特别是对表中的所有N个计数器执行此操作时,这将导致(1 + 2 * N)SELECT。它也没有利用计数器单调增加的事实。

有没有其他方法?我认为其他人也有类似的问题。

一个明显的解决方案当然是填充构造新表或修改现有表的那些NULL值,但不幸的是,在这种情况下这是不可能的。在进入时避免/消除它们也是不可能的。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

select 
   logtime, 
   val, 
   last_value(val ignore nulls) over (order by logtime) 
      as not_null_val,
   last_value(val ignore nulls) over (order by logtime) - 
      last_value(val ignore nulls) over (order by logtime rows between unbounded preceding and 1 preceding) 
      as delta  
from your_tab order by logtime;  

答案 1 :(得分:1)

我找到了一种使用Oracle SQL内置LAG函数来避免嵌套SELECT语句的方法:

SELECT logtime, val,
       NVL(val-LAG(val IGNORE NULLS) OVER (ORDER BY logtime), 0) AS delta
FROM tab;

似乎按照我的意图行事。

(在此作为单独的答案重复)