我正在使用SQL Server 2012构建库存计划/重新排序引擎。
我有一堆过时的交易,称它们为贷方和借方。我想一次做两件事:
该表如下所示:
CREATE TABLE TX (TDate DATETIME, Qty INT); INSERT INTO TX VALUES ('2014-03-01', 20); INSERT INTO TX VALUES ('2014-03-02',-10); INSERT INTO TX VALUES ('2014-03-03',-20); INSERT INTO TX VALUES ('2014-03-04',-10); INSERT INTO TX VALUES ('2014-03-05', 30); INSERT INTO TX VALUES ('2014-03-06',-20); INSERT INTO TX VALUES ('2014-03-07', 10); INSERT INTO TX VALUES ('2014-03-08',-20); INSERT INTO TX VALUES ('2014-03-09', -5);
我正在使用SQL 2012 SUM OVER()窗口函数来显示这些的运行总数。
select TDate, Qty, RunningTotal, RecommendedReplenish from ( select TDate, Qty, SUM(Qty) OVER (ORDER BY TDate ROWS UNBOUNDED PRECEDING) as RunningTotal, -1 * (CASE WHEN Qty < 0 AND SUM(Qty) OVER (ORDER BY TDate ROWS UNBOUNDED PRECEDING) < 0 THEN CASE WHEN Qty > SUM(Qty) OVER (ORDER BY TDate ROWS UNBOUNDED PRECEDING) THEN Qty ELSE SUM(Qty) OVER (ORDER BY TDate ROWS UNBOUNDED PRECEDING) END ELSE 0 END) as RecommendedReplenish /* Wrong, does not account for balance resetting to zero */ from TX ) T order by TDate
我需要找到一种方法将运行总计(又称RT)重置为零(如果下降到零以下)。
我的查询中Qty和RT均为负数,并将其中较大(较小的负数)作为第一个建议的补货。第一次可以正常运行。
我不确定如何从窗口运行总计中扣除这一点。如果可能的话,我想在一个语句中执行此操作。
以下是我要查找的输出的摘要:
TDate Qty R.Tot Replenish New RT ----------- ---- ----- ----------- --------- 3/1/2014 20 20 20 3/2/2014 -10 10 10 3/3/2014 -20 -10 10 0 3/4/2014 -10 -20 10 0 3/5/2014 30 10 30 3/6/2014 -20 -10 10 3/7/2014 10 0 20 3/8/2014 -20 -20 0 3/9/2014 - 5 -25 5 0
Itzik Ben-Gan,Joe Celko或其他SQL英雄,您在那里吗?:)
提前致谢!
这可以使用基于集合的解决方案来完成:
1,计算出正常的跑步总数(称为RT)
2.计算RT的最小运行时间(称其为MN)
当MN为负时,-MN是您到目前为止必须补充的总量。当MN为负时,使replenish_rt为-MN。因此,新的运行总计(称为new_rt)为rt + replenish_rt。并且,如果您需要返回当前所需的补货数量,请从当前值中减去以前的replenish_rt(使用LAG)。
这是完整的解决方案查询:
with c1 as ( select *, sum(qty) over(order by tdate rows unbounded preceding) as rt from tx ), c2 as ( select *, -- when negative, mn is the total qty that had to be -- replenished until now, inclusive min(rt) over(order by tdate rows unbounded preceding) as mn_cur from c1 ) select tdate, qty, rt, replenish_rt - lag(replenish_rt, 1, 0) over(order by tdate) as replenish, rt + replenish_rt as new_rt from c2 cross apply(values(case when mn_cur < 0 then -mn_cur else 0 end)) as a1(replenish_rt);