【问题标题】:Dynamic row range when calculating moving sum/average using window functions (SQL Server)使用窗口函数计算移动总和/平均值时的动态行范围(SQL Server)
【发布时间】:2015-06-24 02:25:12
【问题描述】:

我目前正在编写一个示例脚本,它允许我计算前两行和当前行的总和。但是,我想将数字“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

【问题讨论】:

  • 你能不能建立一个动态的T-SQL 语句然后执行它?
  • 是的,我可以尝试 - 目前这似乎是唯一的出路。但是想检查是否有任何其他“更清洁”的解决方案!非常感谢!

标签: sql sql-server tsql window-functions


【解决方案1】:
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)

【讨论】:

    【解决方案2】:

    您可以尝试这样的不使用动态 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 行。

    【讨论】:

      【解决方案3】:

      如果范围变量的可能离散度不是很高,可以使用简单的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
      

      【讨论】:

        猜你喜欢
        • 2013-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-13
        • 2021-03-06
        • 2019-03-04
        • 2021-03-29
        • 1970-01-01
        相关资源
        最近更新 更多