2012-02-23 53 views
1

我正在处理数据仓库项目,并且客户端提供每日销售数据。大多数生产线都提供现有数量,但通常缺少。我需要帮助如何根据以前的OH和销售信息填补这些缺失的值。
T-SQL - 填补运行余额中的空白

这里的一个示例数据:

Line# Store Item OnHand SalesUnits DateKey 
----------------------------------------------- 
1  001 A  100  20   1  
2  001 A  80  10   2  
3  001 A  null 30   3  --[OH updated with 70 (80-10)] 
4  001 A  null 5   4  --[OH updated with 40 (70-30)] 
5  001 A  150  10   5  --[OH untouched] 
6  001 B  null 4   1  --[OH untouched - new item] 
7  001 B  80  12   2  
8  001 B  null 10   3  --[OH updated with 68 (80-12] 

线路1和2,因为现有量存在的量不被更新。
第3行和第4行将根据其前面的行进行更新。
由于提供了OnHand,因此第5行将保持不变。
6号线将保持不变,因为它是第一行的B项

有没有一种方法,我可以在一组操作做到这一点?我知道我可以使用fast_forward光标轻松完成,但它需要很长时间(15M +行)。

感谢您的帮助!

+0

不要从@Diego运行脚本,它会弄乱你的数据! – 2012-02-23 12:15:08

回答

0

测试数据:

declare @t table(
Line# int, Store char(3), Item char, OnHand int, SalesUnits int, DateKey int 
) 

insert @t values 
(1, '001', 'A', 100, 20, 1), 
(2, '001', 'A', 80 , 10, 2), 
(3, '001', 'A', null, 30, 3), 
(4, '001', 'A', null, 5, 4), 
(5, '001', 'A', 150, 10, 5), 
(6, '001', 'B', null, 4, 1), 
(7, '001', 'B', null, 4, 2), 
(8, '001', 'B', 80, 12, 3), 
(9, '001', 'B', null, 10, 4) 

脚本来填充不使用光标:

;with a as 
(
select Line#, Store, Item, OnHand, SalesUnits, DateKey, 1 correctdata from @t where DateKey = 1 
union all 
select t.Line#, t.Store, t.Item, coalesce(t.OnHand, a.onhand - a.salesunits), t.SalesUnits, t.DateKey, t.OnHand from @t t 
join a on a.DateKey = t.datekey - 1 and a.item = t.item and a.store = t.store 
) 
update t 
set OnHand = a.onhand 
from @t t join a on a.line# = t.line# 
where a.correctdata is null 

脚本来填充使用光标:

declare @datekey int, @store int, @item char, @Onhand int, 
@calculatedonhand int, @salesunits int, @laststore int, @lastitem char 

DECLARE sales_cursor 
CURSOR FOR 
SELECT datekey+1, store, item, OnHand -SalesUnits, salesunits 
FROM @t sales 
order by store, item, datekey 

OPEN sales_cursor; 
FETCH NEXT FROM sales_cursor 
INTO @datekey, @store, @item, @Onhand, @salesunits 

WHILE @@FETCH_STATUS = 0 
BEGIN 
SELECT @calculatedonhand = case when @laststore = @store and @lastitem = @item 
then coalesce(@onhand, @calculatedonhand - @salesunits) else null end 
,@laststore = @store, @lastitem = @item 

UPDATE s 
SET [email protected] 
FROM @t s 
WHERE datekey = @datekey and @store = store and @item = item 
and onhand is null and @calculatedonhand is not null 

FETCH NEXT FROM sales_cursor 
INTO @datekey, @store, @item, @Onhand, @salesunits 

END 
CLOSE sales_cursor; 
DEALLOCATE sales_cursor; 

我推荐你使用光标的版本,我怀疑你可以使用递归查询获得不错的表现。我知道这里的人讨厌游标,但是当你的桌子有这样的尺寸时,它可能是唯一的解决方案。

+0

谢谢 - 在这种情况下,我会坚持用我的good'ol光标。 :) – 2012-02-28 18:26:54

+0

@GustavoCavalcanti不是我自己的游戏迷,但有时他们是一个涅as的邪恶。我希望它能提高你的表现。注意它只更新空行 – 2012-02-28 19:43:15