问题描述
我感觉好像我遗漏了一些应该很明显的非常基本的东西。我基本上是在尝试获取以下数据并计算第五列:Inventory_Current。
示例数据:
日期戳 | 产品ID | Inventory_Change | Inventory_Count |
---|---|---|---|
2021-07-01 | 100 | -300 | 100000 |
2021-07-01 | 200 | -700 | 50000 |
2021-07-02 | 100 | 200 | 空 |
2021-07-02 | 200 | -100 | 空 |
2021-07-03 | 100 | 500 | 空 |
2021-07-03 | 200 | 300 | 空 |
2021-07-04 | 100 | -1000 | 99500 |
2021-07-04 | 200 | -100 | 空 |
2021-07-05 | 100 | 100 | 空 |
2021-07-05 | 200 | 300 | 50500 |
Inventory_Count 通常每月只执行一次,但销售要求 Inventory_Change 每天发生。因此,我需要根据每个 ProductID 自上次 Inventory_Count 以来的 Inventory_Changes 总和来计算当前库存水平。示例数据旨在简洁地表达这一概念。
预期结果:
日期戳 | 产品ID | Inventory_Change | Inventory_Count | Inventory_Current |
---|---|---|---|---|
2021-07-01 | 100 | -300 | 100000 | 99700 |
2021-07-01 | 200 | -700 | 50000 | 49300 |
2021-07-02 | 100 | 200 | 空 | 99900 |
2021-07-02 | 200 | -100 | 空 | 49200 |
2021-07-03 | 100 | 500 | 空 | 100400 |
2021-07-03 | 200 | 300 | 空 | 49500 |
2021-07-04 | 100 | -1000 | 99500 | 98500 |
2021-07-04 | 200 | -100 | 空 | 49400 |
2021-07-05 | 100 | 100 | 空 | 98600 |
2021-07-05 | 200 | 300 | 50500 | 50800 |
要计算 Inventory_Current,我大致遵循以下逻辑:
select
DateStamp,ProductID,Inventory_Change,Inventory_Count,iif(Inventory_Count is not null,Inventory_Count+Inventory_Change,/*Do magic here*/
) as Inventory_Current
from
Inventory
我考虑过 Itzik Ben-Gan 的 Last non Null 概念(很棒,顺便说一句),利用 LAG、OVER PARTITION 或放弃(显然,sql dba 不是我的主要角色)。似乎最大的问题是所有解决方案都依赖于主键,而我的 DateStamp 和 ProductID 组合似乎会导致问题。
即使是一些可靠阅读的链接也将不胜感激。或者远离孩子好好休息一晚。 :)
提前致谢。
解决方法
在没有预期结果的情况下(在撰写本文时),这是一个猜测,但是,我将猜测您希望获得 SUM
值的累积 InventoryChange
{1}} 并将其添加到 NULL
的最后一个非 InventoryCount
值。如果是这样,那么也许这就是您所追求的:
CREATE TABLE dbo.YourTable (DateStamp date,ProductID int,InventoryChange int,InventoryCount int);
GO
INSERT INTO dbo.YourTable
VALUES('2021-07-01',100,-300,100000),('2021-07-01',200,-700,50000),('2021-07-02',null),-100,('2021-07-03',500,300,('2021-07-04',-1000,99500),('2021-07-05',50500);
GO
WITH Groups AS(
SELECT DateStamp,ProductID,InventoryChange,InventoryCount,COUNT(InventoryCount) OVER (PARTITION BY ProductID ORDER BY DateStamp) AS Grp
FROM dbo.YourTable)
SELECT DateStamp,CASE WHEN InventoryCount IS NOT NULL THEN InventoryCount + InventoryChange
ELSE MAX(InventoryCount) OVER (PARTITION BY ProductID,Grp) +
SUM(InventoryChange) OVER (PARTITION BY ProductID,Grp ORDER BY DateStamp)
END AS InventoryCount
FROM Groups
ORDER BY DateStamp;
GO
DROP TABLE dbo.YourTable;
如果您不希望在具有非 InventoryChange
值的行上计算 NULL
的值,则需要在 {{1} 中使用 CASE
表达式}}。