移动平均线/滚动平均线

时间:2013-12-05 18:43:53

标签: sql sql-server sql-server-2008 statistics subquery

我在MS SQL中有2列,其中一列是序列号。和其他是价值观。我需要一个thrird列,它给出了该行和下一个2中值的总和。

实施例

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

所以我需要第三列,其总和为2 + 3 + 1,3 + 1 + 2和So,所以第8和第9行将没有任何值:

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

解决方案是否可以通用,以便我可以将当​​前窗口大小变为将更多3个数字添加到更大的数字,例如60。

4 个答案:

答案 0 :(得分:1)

如果sno字段不是连续的,您可以将row_number()与聚合一起使用:

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;

答案 1 :(得分:1)

以下是展示以下查询的SQL Fiddle

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

在你的问题中,你要求总计3个连续值。您修改了问题,说明您需要总和的连续记录数可能会发生变化。在上面的查询中,您只需将m.RowNumber + 2更改为您需要的内容。

因此,如果您需要60,请使用

m.RowNumber + 59

正如您所看到的,它非常灵活,因为您只需要更改一个数字。

答案 2 :(得分:0)

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

或者,根据您的评论中的要求,您可以这样做:

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

答案 3 :(得分:0)

如果您需要一个完全通用的解决方案,您可以在其中求和,例如,当前行+下一行+第5行:

步骤1:创建一个列出所需偏移的表格。 0 =当前行,1 =下一行,-1 =上一行等

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

步骤2:在此模板中使用该偏移表(通过CTE或实际表格):

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

此外,如果SNo不是连续的,您可以获取ROW_NUMBER()并加入其中。

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