使用LAG功能运行总计

时间:2015-01-12 11:35:28

标签: sql sql-server

我想知道是否有人可以帮我计算一个总计。

我正在从现有的excel解决方案转换它,所以我知道我的目标。

我正在尝试使用LAG从前一行获取值,但计算与我的目标不匹配。我想我需要使用滞后列中前一行的结果,但这看起来不太可能。

任何帮助表示感谢。

use tempdb;

--Create Temp Table 
IF OBJECT_ID('tempdb..#WareHouseData') IS NOT NULL DROP TABLE #WareHouseData
CREATE TABLE #WareHouseData
   ( 
      ItemId    INT,
      DateID    INT,
      OpenningWareHouseUnits INT,
      FcastSales INT,
      GoodsIncoming INT,
      TargetRunningStock INT
   ); 

--Fill It With example Data
--OpenningWareHouseUnits only exists in the first week 
--Fcast sales can be in any week though normally all weeks
--Goods Incoming can be in any weeks
INSERT INTO #WareHouseData  
    ([ItemId],[DateID],[OpenningWareHouseUnits],[FcastSales],[GoodsIncoming],[TargetRunningStock])
VALUES  
(987654,201450,200,10,NULL,190),
(987654,201451,NULL,20,NULL,170),
(987654,201452,NULL,30,NULL,140),
(987654,201501,NULL,20,NULL,120),
(987654,201502,NULL,10,NULL,110),
(987654,201503,NULL,50,NULL,60),
(987654,201504,NULL,60,NULL,0),
(987654,201505,NULL,70,100,30),
(987654,201506,NULL,70,80,40),
(987654,201507,NULL,80,100,60),
(987654,201508,NULL,30,NULL,30),
(987654,201509,NULL,20,NULL,10),
(987654,201510,NULL,20,NULL,0),
(123456,201450,300,50,NULL,250),
(123456,201451,NULL,60,NULL,190),
(123456,201452,NULL,70,100,220),
(123456,201501,NULL,80,NULL,140),
(123456,201502,NULL,100,100,140),
(123456,201503,NULL,105,NULL,35),
(123456,201504,NULL,100,100,35),
(123456,201505,NULL,95,NULL,0),
(123456,201506,NULL,30,100,70),
(123456,201507,NULL,20,NULL,50),
(123456,201508,NULL,5,NULL,45),
(123456,201509,NULL,5,NULL,40),
(123456,201510,NULL,5,NULL,35),
(369258,201450,1000,100,NULL,900),
(369258,201451,NULL,100,NULL,800),
(369258,201452,NULL,100,NULL,700),
(369258,201501,NULL,100,NULL,600),
(369258,201502,NULL,100,NULL,500),
(369258,201503,NULL,100,NULL,400),
(369258,201504,NULL,100,NULL,300),
(369258,201505,NULL,100,NULL,200),
(369258,201506,NULL,100,NULL,100),
(369258,201507,NULL,100,500,500),
(369258,201508,NULL,100,NULL,400),
(369258,201509,NULL,100,NULL,300),
(369258,201510,NULL,100,NULL,200);
;


--Match The Target Runing Stock Total
--I need to match the TargetRunningStock Totals
--This can be recreated in excel by pasting the columns 
--{ItemId   DateID  OpenningWareHouseUnits  FcastSales  GoodsIncoming}
--Into cell A1 with headers, and pasting this formula 
-- =IF(C2="",IF((F1-D2+E2)<0,0,(F1-D2+E2)),(C2-D2+E2)) into cell F2  
SELECT w.ItemId
    ,   w.DateID    
    ,   w.OpenningWareHouseUnits    
    ,   w.FcastSales    
    ,   w.GoodsIncoming 
    ,   w.TargetRunningStock
    ,   CASE WHEN w.OpenningWareHouseUnits IS NOT NULL
             THEN (ISNULL(w.OpenningWareHouseUnits,0) - ISNULL(w.FcastSales,0) + ISNULL(w.GoodsIncoming,0))
             ELSE  CASE WHEN ((((LAG(ISNULL(w.OpenningWareHouseUnits,0),1)  OVER (PARTITION BY w.ItemId  ORDER BY w.ItemId,w.DateID))- 
                                    (LAG(ISNULL(w.FcastSales,0),1)  OVER (PARTITION BY w.ItemId  ORDER BY w.ItemId,w.DateID)) + 
                                        (LAG(ISNULL(w.GoodsIncoming,0),1)  OVER (PARTITION BY w.ItemId  ORDER BY w.ItemId,w.DateID)))) -
                                ISNULL(w.FcastSales,0) + ISNULL(w.GoodsIncoming,0)) < 0
                        THEN 0
                        ELSE ((((LAG(ISNULL(w.OpenningWareHouseUnits,0),1)  OVER (PARTITION BY w.ItemId  ORDER BY w.ItemId,w.DateID))- 
                                    (LAG(ISNULL(w.FcastSales,0),1)  OVER (PARTITION BY w.ItemId  ORDER BY w.ItemId,w.DateID)) + 
                                        (LAG(ISNULL(w.GoodsIncoming,0),1)  OVER (PARTITION BY w.ItemId  ORDER BY w.ItemId,w.DateID)))) -
                                ISNULL(w.FcastSales,0) + ISNULL(w.GoodsIncoming,0))
                     END
            END  CalculatedRunningStock
FROM #WareHouseData w
ORDER BY w.ItemId
    ,   w.DateID    

2 个答案:

答案 0 :(得分:3)

为了简单(和时间)而忽略大部分计算逻辑,您几乎肯定需要sum() over (partition by ... order by...)

select ItemId, DateId, TargetRunningStock, 
       sum(TargetRunningStock) over (partition by itemid order by dateid)
from WarehouseData
order by ItemId, DateId;
ItemId  DateId  TargetRunningStock  Sum
--
123456  201450  250                 250
123456  201451  190                 440
123456  201452  220                 660
...
987654  201507  60                  920
987654  201508  30                  950
987654  201509  10                  960
987654  201510   0                  960

由于您尝试从电子表格中重现结果,因此您可能需要在使用lag()的某些计算列周围包装此类内容。我没有深入了解您的电子表格逻辑。

答案 1 :(得分:1)

运行总和的基本语法是在order by子句中为partition窗口函数使用sum()

SELECT w.ItemId, w.DateID, w.OpenningWareHouseUnits, w.FcastSales,
       w.GoodsIncoming, w.TargetRunningStock,
       SUM(OpenningWareHouseUnits) OVER (PARTITION BY w.ItemId, w.DateId)
FROM #WareHouseData w
ORDER BY w.ItemId, w.DateID ;

我有点不清楚如何将其应用于您的配方。样本数据和期望的结果将是一个很大的帮助。