【问题标题】:Calculate Sum From Moving 4 Rows in SQL从 SQL 中移动 4 行计算总和
【发布时间】:2016-04-09 21:17:54
【问题描述】:

我有以下数据。

   WM_Week  POS_Store_Count POS_Qty POS_Sales   POS_Cost
   ------   --------------- ------  --------    --------
   201541   3965            77722   153904.67   102593.04
   201542   3952            77866   154219.66   102783.12
   201543   3951            70690   139967.06   94724.60
   201544   3958            70773   140131.41   95543.55
   201545   3958            76623   151739.31   103441.05
   201546   3956            73236   145016.54   98868.60
   201547   3939            64317   127368.62   86827.95
   201548   3927            60762   120309.32   82028.70

我需要编写一个 SQL 查询来获取最后 4 周的数据,并将它们的最后 4 周对以下列中的每一列求和:POS_Store_CountPOS_QtyPOS_SalesPOS_Cost

例如,如果我想要 201548 的数据,它将包含 201548、201547、201546 和 201545 的数据。

201547 的总和将包含 201547、201546、201545 和 201544。

查询成功后应返回 4 行。

我将如何制定一个递归查询来做到这一点?有什么比递归更简单的方法吗?

编辑:版本是 Azure Sql DW,版本号为 12.0.2000。 Edit2:应该返回的四行将具有来自其自身的列的总和,并且是前三周。

例如,如果我想要 201548 的数字,它将返回以下内容:

WM_Week POS_Store_Count POS_Qty  POS_Sales   POS_Cost
------  --------------- -------  --------    --------
201548  15780           274938   544433.79   371166.3

这是来自201548201547201546201545 的四个(非身份)列的总和。

【问题讨论】:

  • 到目前为止您尝试过什么查询?
  • 你想sum做什么?您可能可以通过使用topwhereorder by desc 的非常基本的查询来做到这一点...
  • @sgeddes 抱歉,我正在尝试总结 POS_Store_CountPOS_QtyPOS_SalesPOS_Cost 列。我会相应地更新我的问题。
  • 什么版本的 SQL Server?
  • @Love2Learn Azure Sql 数据仓库。看起来好像版本是 12.0.2000。

标签: sql sql-server azure-sqldw


【解决方案1】:

很确定这会让你得到你想要的。我在订购数据后使用交叉应用来应用 SUMS

Create  Table #WeeklyData (WM_Week Int, POS_Store_Count Int, POS_Qty Int, POS_Sales Money, POS_Cost Money)

Insert #WeeklyData Values
(201541,3965,77722,153904.67,102593.04),
(201542,3952,77866,154219.66,102783.12),
(201543,3951,70690,139967.06,94724.6),
(201544,3958,70773,140131.41,95543.55),
(201545,3958,76623,151739.31,103441.05),
(201546,3956,73236,145016.54,98868.6),
(201547,3939,64317,127368.62,86827.95),
(201548,3927,60762,120309.32,82028.7)

DECLARE @StartWeek INT = 201548;
WITH cte AS
(
    SELECT *, 
            ROW_NUMBER() OVER (ORDER BY [WM_Week] DESC) rn
    FROM #WeeklyData 
    WHERE WM_Week BETWEEN @StartWeek - 9 AND @StartWeek  
)
SELECT *
FROM cte c1
CROSS APPLY (SELECT SUM(POS_Store_Count) POS_Store_Count_SUM, 
                    SUM(POS_Qty) POS_Qty_SUM, 
                    SUM(POS_Sales) POS_Sales_SUM,
                    SUM(POS_Cost) POS_Cost_SUM
             FROM   cte c2 
             WHERE  c2.rn BETWEEN c1.rn AND (c1.rn + 3)
) ca     
WHERE c1.rn <= 4 

【讨论】:

  • 我想这就是你想要的。 @JamieD77 考虑了一切。我添加了记录,因此您可以使用提供的输入对其进行测试,因为我至少做了这么多。 :)
  • @Love2Learn 谢谢!.. 由于某种原因,Sql fiddle 现在不适合我,否则我会在那里展示我的工作
  • 太棒了!这几乎就是我想要的。现在唯一的问题是我实际上还有 15 列左右,所以我需要集成到其中。而且查询的性能很糟糕。不过谢谢你的回答!
  • 您可以尝试使用临时表而不是 CTE.. 这可能会加快一些速度.. 我不认为只选择 9 行会那么慢..
  • 我们实际上是使用它作为视图,所以使用临时表不是一个选项。不过感谢您的信息!
【解决方案2】:

您可以将SUM()OVER Clause 结合使用

类似:

SELECT WM_Week.
, SUM(POS_Store_Count) OVER (ORDER BY WM_Week ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)
FROM Table

【讨论】:

    【解决方案3】:

    您应该能够为此使用 SQL 窗口函数。

    向您的查询添加一列,如下所示:

    SUM(POS_Sales) OVER(
       ORDER BY WM_Week 
       ROWS BETWEEN 3 PRECEDING AND CURRENT ROW
    ) AS POS_Sales_4_Weeks
    

    【讨论】:

      【解决方案4】:

      如果我理解正确,您不想返回 4 行,而是为每个组返回 4 个总和列?如果是这样,这是一种选择:

      select max(WM_Week) as WM_Week,
             sum(POS_Store_Count),
             sum(POS_Qty),
             sum(POS_Sales),
             sum(POS_Cost)
      from (select top 4 *
            from yourtable
            where wm_week <= 201548
            order by wm_week desc) t
      

      这使用带有top 的子查询来根据where 条件和order by 子句获取要聚合的4 行。


      这是一个精简的fiddle 演示示例(抱歉,fiddle 目前不支持 sql server,因此语法略有偏差):

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-17
        • 2019-08-24
        相关资源
        最近更新 更多