T-SQL计算移动平均线

Run*_*unW 16 sql t-sql sql-server-2008-r2 moving-average window-functions

我正在使用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 | 
Run Code Online (Sandbox Code Playgroud)

TransactionID是独特的.对于每一个TransactionID,我想计算列值的平均值,超过之前的250个记录.因此,对于TransactionID 300,收集前250行的所有值(视图按TransactionID降序排序),然后在MovAvg列中写入这些值的平均值的结果.我希望收集一系列记录中的数据.

jpw*_*jpw 21

与更高版本相比,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
Run Code Online (Sandbox Code Playgroud)

请注意,它将相关的子查询应用于每一行,性能可能不是很好.

使用更高版本,您可以使用窗口框架功能并完成以下操作:

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
Run Code Online (Sandbox Code Playgroud)


Ada*_*rad 6

使用公用表表达式(CTE)为每个事务包含rownum,然后在行号上加入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 
Run Code Online (Sandbox Code Playgroud)