web-dev-qa-db-ja.com

T-SQLは移動平均を計算します

SQL Server 2008 R2を使用して、移動平均を計算しようとしています。私のビューの各レコードについて、以前の250個のレコードの値を収集してから、この選択の平均を計算します。

私のビューの列は次のとおりです。

TransactionID | TimeStamp           | Value | MovAvg
----------------------------------------------------
            1 | 01.09.2014 10:00:12 |     5 |    
            2 | 01.09.2014 10:05:34 |     3 | 
...
          300 | 03.09.2014 09:00:23 |     4 | 

TransactionIDは一意です。各TransactionIDについて、以前の250レコードの列値の平均を計算したいと思います。したがって、TransactionID 300の場合、前の250行からすべての値を収集し(ビューはTransactionIDの降順でソートされます)、列MovAvgにこれらの値の平均の結果を書き込みます。ある範囲のレコード内のデータを収集したいと考えています。

16
RunW

SQL 2008のウィンドウ関数は、それ以降のバージョンに比べてかなり制限されており、私が正しいことを覚えている場合は、パーティション分割しかできず、行/範囲フレームの制限は使用できませんが、これはあなたが望むものだと思います:

;WITH cte (rn, transactionid, value) AS (
    SELECT 
       rn = ROW_NUMBER() OVER (ORDER BY transactionid),
       transactionid,
       value
    FROM your_table
)

SELECT 
    transactionid, 
    value, 
    movagv = (
        SELECT AVG(value) 
        FROM cte AS inner_ref
        -- average is calculated for 250 previous to current row inclusive
        -- I might have set the limit one row to large, maybe it should be 249
        WHERE inner_ref.rn BETWEEN outer_ref.rn-250 AND outer_ref.rn
        ) 
FROM cte AS outer_ref

相関サブクエリがすべての行に適用されるため、パフォーマンスはそれほど高くない場合があります。

それ以降のバージョンでは、ウィンドウフレーム関数を使用して、次のようなことを行うことができます。

SELECT 
    transactionid, 
    value,
    -- avg over the 250 rows counting from the previous row
    AVG(value) OVER (ORDER BY transactionid  
                     ROWS BETWEEN 251 PRECEDING AND 1 PRECEDING),
    -- or 250 rows counting from current
    AVG(value) OVER (ORDER BY transactionid  
                     ROWS BETWEEN 250 PRECEDING AND CURRENT ROW)
FROM your_table
21
jpw

共通テーブル式(CTE) を使用して各トランザクションの行番号を含め、CTEを行番号で結合して、以前の値を取得して平均を計算できるようにします。

CREATE TABLE MyTable (TransactionId INT, Value INT)

;with Data as
(
  SELECT TransactionId, 
         Value, 
         ROW_NUMBER() OVER (ORDER BY TransactionId ASC) as rownum
  FROM MyTable
)
SELECT d.TransactionId , Avg(h.Value) as MovingAverage
FROM Data d
JOIN Data h on h.rownum between d.rownum-250 and d.rownum-1
GROUP BY d.TransactionId 
6
Adam Porad