0

列を持つテーブルがありMeasuresます: timestamp(Unix タイムスタンプ), tag, value. たとえば、15 日間の単一の移動平均を取得するには、次のようにします。

SELECT tag,avg(value) 
FROM measures 
 WHERE tag='xtr' 
 AND timestamp<1353304800
 AND timestamp>1350622800 
 GROUP BY tag;

今、最新の 150 行の移動平均を取得したいのですが、クエリの方法がわかりません。

SELECT t, s,avg(bv) 
FROM 
  (SELECT A.timestamp as t,A.tag as ta,A.value as ac, B.timestamp as tb,B.value as bv, 
  FROM measures 
  CROSS JOIN measures B 
  WHERE A.tag='xtr' AND B.tag='xtr' 
  GROUP BY A.tag) WHERE ROWNUM <= 150;

これは明らかに間違っていますが、私はそれについて考えていて、理解できません。何か案は?私の考えでは、各エントリをその下の 150 エントリと照合し、valueそれらの 150 エントリの平均を計算する必要があります。CROSS JOINまた、非常に遅くなるため、 を使用しないほうがよい方法があると確信しています。

4

3 に答える 3

6

テーブル構造とデータの一意性が完全に明確ではありませんが、このクエリは、すべてのタイムスタンプについて前の 150 行 (現在の行を含む) の真の移動平均を提供します。

SELECT
  tag,
  timestamp,
  avg(value) over (partition by tag
                   order by timestamp asc
                   rows between 149 preceding and current row) moving_avg
FROM
  measures 
WHERE
  tag='xtr' 

最新の 150 行を分離する必要がある場合は、次のクエリに基づいてください。

select
  tag,
  value
from(
  select tag
         value
  from measures
  order by timestamp desc)
where
  rownum <= 150
于 2012-11-19T10:08:44.640 に答える
0
WITH
  sequenced AS
(
  SELECT
    ROW_NUMBER() OVER (PARTITION BY tag ORDER BY timestamp) AS sequence_id,
    *
  FROM
    measures
)
SELECT
  measure.tag,
  measure.timestamp,
  AVG(history.value)
FROM
  sequenced           AS measure
INNER JOIN
  sequenced           AS history
    ON  history.tag          = measure.tag
    AND history.sequence_id >  measure.sequence_id - 150
    AND history.sequence_id <= measure.sequence_id
GROUP BY
  measure.tag,
  measure.timestamp

あまり効率的ではありません。すべての行が他の 150 行に結合されます。しかし、これは、ORACLE のほとんどの(比較的最近の)バージョンがサポートすることを私が知っている最も簡単な方法です。

于 2012-11-19T09:54:08.130 に答える
0

Oracleにはパッケージがあり、パッケージを使用して独自の移動平均関数を作成できます。

アプリケーションをテストする十分な時間がありませんが、理論的には動作するはずです (Oracle のみ)

「パッケージ本体で宣言された変数は、セッション全体で存続します (値を保持します)。」

Create or replace package xxx ;
procedure clearMovingAverage ;
function movingAverage (newAVG in number) return number ;
end ;
/

create or replace package body xxx ;
movTot number ;
movCnt number ;
procedure clearMovingAverage is 
begin
  movTot := 0 ;
  movCnt := 0 ;
end ;
function movingAverage (newAvg in number) return number is 
begin
  if newAvg is not null then 
     movTot := movTot + newAvg ;
     movCnt := movCnt + 1 ;
  end if ;
  return movTot / movCnt ;
end ;
end ;
/

利用方法:

begin
  xxx.clearMovingAverage ;
  select tag,xxx.movingAverage(avg(value)) 
    FROM measures 
  ..... 
   group by tag ;
end ;

また

begin
  xxx.clearMovingAverage ;
  select tag, xxx.MovingAverage(avgValue) 
    from (select tag,avg(value) avgValue 
          FROM measures 
          ..... 
          group by tag)
end ;

このコードが役立つことを願っています...

于 2012-11-19T11:25:54.923 に答える