1

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

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

我必须计算从每个日志时间到前一个日志时间的增量。使用此处另一个问题中描述的方法为每个 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) SELECTs。它也没有利用计数器单调递增的事实。

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

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

任何帮助将不胜感激。

4

2 回答 2

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;  
于 2013-03-14T12:48:39.687 回答
1

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

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

似乎按我的意图工作。

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

于 2013-03-15T08:15:41.043 回答