3

数値分析、特に関心のある 3 つの列 (タイムスタンプ、デバイス ID、値) を持つテーブルでの線形補間に Oracle 11g (開発では 11.1、運用では 11.2) を使用しようとしています。

値の列には、タイムスタンプで指定された時点で取得されたデバイス (id deviceid を持つ) からのデータが保持されます。たとえば、これは偽のデータですが、アイデアは次のようになります。

     time       |  deviceid  |  value   
----------------|------------|-----------
 01:00:00.000   |  001       | 1.000
 01:00:01.000   |  001       | 1.030
 01:00:02.000   |  001       | 1.063 
 01:00:00.050   |  002       | 553.10
 01:00:01.355   |  002       | 552.30
 01:00:02.155   |  002       | 552.43 

デバイス 001 からのタイムスタンプはデバイス 002 のタイムスタンプと一致しませんが、デバイス 001 と 002 の両方からの値を 1 つの行に、1 つのタイムスタンプで、デバイス 001 のタイムスタンプと一致させる必要があります。このようなもの:

     time       |  device 001  |  device 002   
----------------|--------------|------------
 01:00:00.000   |  1.000       |  null
 01:00:01.000   |  1.030       |  552.520
 01:00:02.000   |  1.063       |  552.405

デバイス 002 の値は、デバイス 001 の各タイムスタンプの両側にある 2 つの最も近いタイムスタンプで収集されたデバイス 002 の値に基づいて線形補間されました。 01:00:00.000 であり、値を外挿したくありません。

私が理解していることから、percentile_cont を使用してこれを行うことができますが、オンラインで見た例がわかりません。たとえば、percentile_cont で使用されるパーセンタイルはどこから来るのでしょうか?

よろしくお願いします。

4

3 に答える 3

3

求める補間を行うためにどのように使用するかはわかりませんPERCENTILE_CONTが、別の分析関数の助けを借りて、目的を達成できます。

まず、INTERVAL DAY TO SECOND値を秒に変換する次の関数を作成します。

CREATE OR REPLACE FUNCTION intvl_to_seconds(
    p_interval INTERVAL DAY TO SECOND
) RETURN NUMBER DETERMINISTIC
AS
BEGIN
  RETURN EXTRACT(DAY FROM p_interval) * 24*60*60
       + EXTRACT(HOUR FROM p_interval) * 60*60
       + EXTRACT(MINUTE FROM p_interval) * 60
       + EXTRACT(SECOND FROM p_interval);
END;
/

この関数を使用すると、次のようなクエリを使用できます。

SELECT d1.time,
       d1.value AS value1,
       q2.prev_value + intvl_to_seconds(d1.time - q2.prev_time) * (q2.next_value - q2.prev_value)/intvl_to_seconds(q2.next_time - q2.prev_time) AS value2
  FROM devices d1
  LEFT OUTER JOIN (SELECT d2.time AS prev_time,
                          d2.value AS prev_value,
                          LEAD(d2.time, 1) OVER (ORDER BY d2.time) AS next_time,
                          LEAD(d2.value, 1) OVER (ORDER BY d2.time) AS next_value
                     FROM devices d2
                    WHERE d2.deviceid = 2) q2
               ON d1.time BETWEEN q2.prev_time AND q2.next_time
 WHERE d1.deviceid = 1;

上記のデータを取得し、タイムスタンプの日付コンポーネントを今日に設定しました。上記のクエリを実行すると、次の結果が得られました。

TO_CHAR(D1.TIME) VALUE1 VALUE2
-------------------------------------- ---------- --- -------
2011 年 9 月 9 日 01.00.00.000000 1
09-SEP-11 01.00.01.000000 1.03 552.517625
09-SEP-11 01.00.02.000000 1.063 552.404813

( SQL*Plus で過剰なスペースを削減するために、TO_CHARアラウンドを追加しました。)d1.time

DATEs の代わりにsを使用している場合TIMESTAMP、関数は必要ありません。日付を減算するだけです。

于 2011-09-09T21:43:47.863 に答える
0

@Luke Woodwardのクエリの修正版を使用しています:

SELECT d1.time,
   d1.value AS value1,
   q2.prev_value + 
   (EXTRACT( SECOND FROM (d1.time - q2.prev_time)) +
    EXTRACT( MINUTE FROM (d1.time - q2.prev_time)) * 60 ) 
    * (q2.next_value - q2.prev_value)/
      (EXTRACT ( SECOND FROM (q2.next_time - q2.prev_time)) + 
      EXTRACT ( MINUTE FROM (q2.next_time - q2.prev_time)) * 60)  AS value2
FROM devices d1
LEFT OUTER JOIN (SELECT d2.time AS prev_time,
                      d2.value AS prev_value,
                      LEAD(d2.time, 1) OVER (ORDER BY d2.time) AS next_time,
                      LEAD(d2.value, 1) OVER (ORDER BY d2.time) AS next_value
                 FROM devices d2
                WHERE d2.deviceid = 2
                      and time between '20100914 000000' and '20100915 000000'
                ) q2
           ON d1.time BETWEEN q2.prev_time AND q2.next_time
 WHERE d1.deviceid = 1;

ただし、日付範囲にデバイス 2 のデータがある場合でも、補間された値は常に null として表示されます。

q2 のクエリの日付範囲を追加する必要があったことに注意してください。これが、おそらく通常の結合で外部データが失われる理由です。

通常の結合を使用すると、補間されたデータの null 値は取得されませんが、通常の結合を使用すると、デバイス 2 (q2 の補間されたデバイス) のエンドポイントの外側にあるデバイス 1 のデータが失われます。提案?

于 2011-09-16T16:50:44.027 に答える