T-SQL calculate moving average

后端 未结 2 1300
长发绾君心
长发绾君心 2020-12-01 16:23

I am working with SQL Server 2008 R2, trying to calculate a moving average. For each record in my view, I would like to collect the values of the 250 previous records, and t

相关标签:
2条回答
  • 2020-12-01 16:45

    The window functions in SQL 2008 are rather limited compared to later versions and if I remember correct you can only partition and you can't use any rows/range frame limit but I think this might be what you want:

    ;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
    

    Note that it applies a correlated sub-query to every row and performance might not be great.

    With the later versions you could have used window frame functions and done something like this:

    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
    
    0 讨论(0)
  • 2020-12-01 16:49

    Use a Common Table Expression (CTE) to include the rownum for each transaction, then join the CTE against itself on the row number so you can get the previous values to calculate the average with.

    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 
    
    0 讨论(0)
提交回复
热议问题