2013-03-14 79 views
1

我有一个由logtime/value1,value2 ...元组以及其他列(如测量点标识)组成的Oracle表。这些值是不同计数器的采样值,每个计数器单调递增,即较新的值不能小于较旧的值。但是,对于多个采样,值可以保持相等,并且值有时可能会丢失,因此相应的表条目为NULL,而同一个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)选择这样做时尤其如此。它也没有从柜台单调增加的事实中获益。

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

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

任何帮助将不胜感激。

+0

如果通过柜台按时间和次序命令他们,那么你可以用户http://www.oracle-base.com/articles/misc/lag-lead -analytic-functions.php#lag – Sibster 2013-03-14 12:38:30

回答

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; 
+0

我发现了一种避免使用Oracle SQL内置LAG函数的嵌套SELECT语句的方法: SELECT logtime,val, NVL(val-LAG(val IGNORE NULLS)OVER(ORDER BY日志时间),0)AS增量 FROM标签; 似乎按照我的意图工作。 – Stefan 2013-03-14 12:51:15

+0

@stefan - 然后在这里发布您的解决方案。 (你可以回答你自己的问题)。 – APC 2013-03-14 12:53:02

+0

@Stefan - 你自己的解决方案比我的更好。 – 2013-03-14 13:08:50

1

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

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

似乎工作,我打算。

(这里重复作为一个单独的答案)