使用窗口函数计算移动总和/平均值时的动态行范围(SQL Server)

时间:2015-04-17 09:44:15

标签: sql sql-server tsql window-functions

我正在研究一个示例脚本,它允许我计算前两行和当前行的总和。但是,我想将数字'2'作为变量。我已经尝试声明一个变量,或直接在查询中强制转换,但总会弹出语法错误。有可能的解决方案吗?

DECLARE @myTable TABLE  (myValue INT)

INSERT INTO @myTable ( myValue ) VALUES  ( 5)
INSERT INTO @myTable ( myValue ) VALUES  ( 6)
INSERT INTO @myTable ( myValue ) VALUES  ( 7)
INSERT INTO @myTable ( myValue ) VALUES  ( 8)
INSERT INTO @myTable ( myValue ) VALUES  ( 9)
INSERT INTO @myTable ( myValue ) VALUES  ( 10)

SELECT 
    SUM(myValue) OVER (ORDER BY myValue 
                       ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
FROM @myTable

3 个答案:

答案 0 :(得分:6)

DECLARE @test VARCHAR = 1
DECLARE @sqlCommand VARCHAR(1000)
DECLARE @myTable TABLE  (myValue INT)

INSERT INTO @myTable ( myValue ) VALUES  ( 5)
INSERT INTO @myTable ( myValue ) VALUES  ( 6)
INSERT INTO @myTable ( myValue ) VALUES  ( 7)
INSERT INTO @myTable ( myValue ) VALUES  ( 8)
INSERT INTO @myTable ( myValue ) VALUES  ( 9)
INSERT INTO @myTable ( myValue ) VALUES  ( 10)

SET @sqlCommand = 'SELECT SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN ' + @test + ' PRECEDING AND CURRENT ROW)
                  FROM #temp'

EXEC (@sqlCommand)

答案 1 :(得分:4)

您可以尝试使用不使用动态SQL的类似内容。

DECLARE @myTable TABLE  (myValue INT)

INSERT INTO @myTable ( myValue ) VALUES  ( 5)
INSERT INTO @myTable ( myValue ) VALUES  ( 6)
INSERT INTO @myTable ( myValue ) VALUES  ( 7)
INSERT INTO @myTable ( myValue ) VALUES  ( 8)
INSERT INTO @myTable ( myValue ) VALUES  ( 9)
INSERT INTO @myTable ( myValue ) VALUES  ( 10)


DECLARE @prev_records INT = 2

;WITH CTE as 
(
SELECT ROW_NUMBER() OVER(ORDER BY myValue) rn,myValue FROM @myTable
)
SELECT (SELECT  SUM(myValue) FROM CTE t2 WHERE t2.rn BETWEEN (t1.rn  - @prev_records) AND t1.rn )
FROM CTE t1

SUM(myValue) OVER()是最佳选择,但它不允许您使用变量传递前N行。

答案 2 :(得分:1)

如果范围变量的可能分散不是很高,您可以使用简单的CASE语句在计算之间切换

DECLARE @myTable TABLE  (myValue INT)

-- let's say it could be between 1 and 10
DECLARE @range int = 3;

INSERT INTO @myTable ( myValue ) VALUES  ( 5)
INSERT INTO @myTable ( myValue ) VALUES  ( 6)
INSERT INTO @myTable ( myValue ) VALUES  ( 7)
INSERT INTO @myTable ( myValue ) VALUES  ( 8)
INSERT INTO @myTable ( myValue ) VALUES  ( 9)
INSERT INTO @myTable ( myValue ) VALUES  ( 10)

SELECT 
    CASE @range
        WHEN 1 THEN SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
        WHEN 2 THEN SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
        WHEN 3 THEN SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)
        WHEN 4 THEN SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN 4 PRECEDING AND CURRENT ROW)
        WHEN 5 THEN SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN 5 PRECEDING AND CURRENT ROW)
        WHEN 6 THEN SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN 6 PRECEDING AND CURRENT ROW)
        WHEN 7 THEN SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN 7 PRECEDING AND CURRENT ROW)
        WHEN 8 THEN SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN 8 PRECEDING AND CURRENT ROW)
        WHEN 9 THEN SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN 9 PRECEDING AND CURRENT ROW)
        WHEN 10 THEN SUM(myValue) OVER (ORDER BY myValue ROWS BETWEEN 10 PRECEDING AND CURRENT ROW)
    END
FROM @myTable