1

logtime / value1、value2 ...のタプルと、メータリングポイントIDなどの追加の列で構成されるOracleテーブルがあります。値は、それぞれが単調に増加するさまざまなカウンターのサンプル値です。つまり、新しい値を古い値より小さくすることはできません。ただし、値は複数のサンプリングで同じままである可​​能性があり、値が失われることがあるため、対応するテーブルエントリはNULLであり、同じログ時間の他の値は有効です。また、logtime間の間隔は一定ではありません。

以下では、簡単にするために、logtimeと1つのカウンター値のみを考慮します。

各ログ時間から前のログ時間までのデルタを計算する必要があります。ここで別の質問で説明されている方法を使用すると、2つの減算が無効であるため、NULL値ごとに2つのNULLデルタが得られます。前の値との差が2回計算されるため、連続する値が同一の場合、2番目のソリューションは失敗します。

別の解決策は、これらの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値を入力して新しいテーブルを作成するか、既存のテーブルを変更することですが、残念ながら、この場合は不可能です。入場時にそれらを回避/排除することもできません。

どんな助けでも大歓迎です。

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 に答える