我有一个dbo.StockLocationHistoryTable,如下所示:
SELECT * FROM dbo.StockLocationHistory AS slh
StockIdentifier | DateScanned | WarehouseLocation
-------------------------------------------------
72825 | 2016-07-03 16:41:24.077 | 854
30509 | 2016-07-03 16:41:24.077 | 854
30509 | 2016-07-05 08:22:10.056 | 854
30509 | 2016-07-06 14:22:15.099 | 628
30509 | 2016-07-08 15:28:22.542 | 628
72825 | 2016-07-08 15:32:25.256 | 778
30509 | 2016-07-10 18:22:24.556 | 854
前提是每次员工进行库存处理时,都会为该产品和产品所在的位置添加一行。因此,从上表中我们看到产品72825在第3个位置扫描了854然后在778号位置再次扫描。
不幸的是,当软件检测到产品位于与之前扫描不同的位置时,软件不会输入StockOUT记录。我正在尝试(未成功)创建详细说明位置历史记录的位置分类帐。
我只关心何时将股票添加到某个位置并从某个位置移除,而不是临时扫描(EG:第一个代码块中的第3行)。我还需要详细说明如代码区块2所示,当在新位置检测到股票为StockOUT事件时。
我需要的是以下内容:
DECLARE @WarehouseLocation INT = 854
[DateScanned] | StockIdentifier | EventType | StockLevel
------------------------------------------------------------------
2016-07-03 16:41:24.077 | 30509 | StockIN | 1
2016-07-03 16:41:24.077 | 72825 | StockIN | 2
2016-07-06 14:22:15.099 | 30509 | StockOUT | 1
2016-07-08 15:32:25.256 | 72825 | StockOUT | 0
2016-07-10 18:22:24.556 | 30509 | StockIN | 1
答案 0 :(得分:0)
我强烈建议您考虑获取这些数据的其他方法。原因是SQL变得复杂,在我看来,效果不是很好。您可以考虑结构或表处理中的更改。
如果没有,或许在应用程序级别更容易计算StockLevel(不需要中间表)。
目标表重命名为@t,代码更小。引入“@ intermediate.id”以正确计算StockLevel(因为DateScanned不是唯一的)。 最后“ORDER BY”是为了保证正确的顺序(因为“GROUP BY”并不保证所有情况都这样)。
declare @WarehouseLocation int = 854
declare @intermediate table(id int identity primary key, DateScanned datetime, StockIdentifier int, EventType char(8))
insert @intermediate
select tin.DateScanned, tin.StockIdentifier, 'StockIN' as EventType from @t tin
where tin.WarehouseLocation = @WarehouseLocation
and not exists(select * from @t t
where t.StockIdentifier = tin.StockIdentifier
and t.WarehouseLocation = @WarehouseLocation
and t.DateScanned < tin.DateScanned
and not exists(select * from @t tout
where tout.StockIdentifier = t.StockIdentifier
and tout.DateScanned > t.DateScanned and tout.DateScanned < tin.DateScanned
and tout.WarehouseLocation != @WarehouseLocation))
union all
select tout.DateScanned, tout.StockIdentifier, 'StockOUT' as EventType from @t tout
where tout.WarehouseLocation != @WarehouseLocation
and not exists(select * from @t t
where t.StockIdentifier = tout.StockIdentifier
and t.WarehouseLocation != @WarehouseLocation
and t.DateScanned < tout.DateScanned
and not exists(select * from @t tin
where tin.StockIdentifier = t.StockIdentifier
and tin.DateScanned > t.DateScanned and tin.DateScanned < tout.DateScanned
and tin.WarehouseLocation = @WarehouseLocation))
order by DateScanned
select t.DateScanned, t.StockIdentifier, t.EventType,
sum(case when prev.EventType = 'StockIn' then 1 else -1 end) as StockLevel
from @intermediate t left join @intermediate prev on prev.id <= t.id
group by t.DateScanned, t.StockIdentifier, t.EventType
order by t.DateScanned