55476

# Moving Average / Rolling Average

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.

Here is the <strong>SQL Fiddle</strong> 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.

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; ```

```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 ```

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 ```