Данные испытаний:
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 onhand=@calculatedonhand
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;
Я рекомендую вам использовать версию курсора, я сомневаюсь, что вы можете получить приличную производительность, используя рекурсивный запрос Я знаю, что люди здесь ненавидят курсоры, но когда ваш стол имеет такой размер, это может быть единственным решением.