2012-02-23 3 views
1

Я работаю над проектом Data Warehouse, и клиент ежедневно предоставляет данные о продажах. Количество в руке в большинстве случаев предоставляется, но часто отсутствует. Мне нужна помощь в том, как заполнить эти недостающие значения на основе предыдущих ОН и информации о продажах.
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 не должны быть обновлены, поскольку существует OnHand величины.
Строки 3 и 4 должны обновляться на основе предыдущих строк.
Строка 5 должна быть оставлена ​​нетронутой, поскольку предоставляется OnHand.
Line 6 необходимо оставить нетронутым, потому что это первая строку для обозначеннной

Есть ли способ, что я могу сделать это в операции настройки? Я знаю, что я могу сделать это легко, используя быстрый движок quick_forward, но это займет много времени (15M + строк).

Благодарим за помощь!

+0

Не запускайте скрипт из @Diego, это испортит ваши данные! –

ответ

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; 

I Recommand вы используете версию курсора, я сомневайтесь, что вы можете получить приличную производительность, используя рекурсивный запрос. Я знаю, что люди здесь ненавидят курсоры, но когда ваш стол имеет такой размер, это может быть единственным решением.

+0

Спасибо. В этом случае я буду придерживаться своего хорошего курсора. :) –

+0

@GustavoCavalcanti не большой поклонник курсоров, но иногда они являются неотъемлемым злом. Надеюсь, это улучшило вашу производительность. Обратите внимание, что он обновляет только нулевые строки –

 Смежные вопросы

  • Нет связанных вопросов^_^