Moving Average / Rolling Average

爱⌒轻易说出口 提交于 2019-12-13 15:42:16

问题


I have 2 columns in MS SQL one is Serial no. and other is values. I need the thrird column which gives me the sum of the value in that row and the next 2.

Ex

SNo values
1 2
2 3
3 1
4 2
5 6
7 9
8 3
9 2

So I need third column which has sum of 2+3+1, 3+1+2 and So on, so the 8th and 9th row will not have any values:

1   2   6   
2   3   6   
3   1   4   
4   2   5   
5   1   6   
7   2   7   
8   3       
9   2       

Can the Solution be generic so that I can Varry the current window size of adding 3 numbers to a bigger number say 60.


回答1:


Here is the SQL Fiddle that demonstrates the following query:

WITH TempS as 
(
  SELECT s.SNo, s.value, 
  ROW_NUMBER() OVER (ORDER BY s.SNo) AS RowNumber
  FROM MyTable AS s
)
SELECT m.SNo, m.value,
(
  SELECT SUM(s.value) 
  FROM TempS AS s
  WHERE RowNumber >= m.RowNumber
  AND RowNumber <= m.RowNumber + 2
) AS Sum3InRow
FROM TempS AS m

In your question you were asking to sum 3 consecutive values. You modified your question saying the number of consecutive records you need to sum could change. In the above query you simple need to change the m.RowNumber + 2 to what ever you need.

So if you need 60, then use

m.RowNumber + 59

As you can see it is very flexible since you only have to change one number.




回答2:


In case the sno field is not sequential, you can use row_number() with aggregation:

with ss as (
      select sno, values, row_number() over (order by sno) as seqnum
      from s
     )
select s1.sno, s1.values,
       (case when count(s2.values) = 3 then sum(s2.values) end) as avg3
from ss s1 left outer join
     ss s2
     on s2.seqnum between s1.seqnum - 2 and s1.seqnum
group by s1.sno, s1.values;



回答3:


select one.sno, one.values, one.values+two.values+three.values as thesum
from yourtable as one
left join yourtable as two
on one.sno=two.sno-1
left join yourtable as three
on one.sno=three.sno-2

Or, as requested in your comment, you could do this:

select sno, sum(values)
over (
    order by sno
    rows between current row and 3 following
)
from yourtable



回答4:


If you need a fully generic solution, where you can sum, for example, current row + next row + 5th following row:

Step 1: Create an table listing the offsets needed. 0 = current row, 1 = next row, -1 = prev row, etc

SELECT * FROM (VALUES
  (0),(1),(2)
) o(offset)

Step 2: Use that offset table in this template (via CTE or an actual table):

WITH o AS (SELECT * FROM (VALUES (0),(1),(2) ) o(offset))
SELECT
  t1.sno,
  t1.value,
  SUM(t2.Value)
FROM @t t1
INNER JOIN @t t2 CROSS JOIN o
  ON t2.sno = t1.sno + o.offset
GROUP BY t1.sno,t1.value
ORDER BY t1.sno

Also, if SNo is not sequential, you can fetch ROW_NUMBER() and join on that instead.

WITH
  o AS (SELECT * FROM (VALUES (0),(1),(2) ) o(offset)),
  t AS (SELECT *,ROW_NUMBER() OVER(ORDER BY sno) i FROM @t)
SELECT
  t1.sno,
  t1.value,
  SUM(t2.Value)
FROM t t1
INNER JOIN t t2 CROSS JOIN o
  ON t2.i = t1.i + o.offset
GROUP BY t1.sno,t1.value
ORDER BY t1.sno


来源:https://stackoverflow.com/questions/20408060/moving-average-rolling-average

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!