SQL альтернатива курсору при манипулировании значениями связанных строк - PullRequest
1 голос
/ 14 июля 2011

У меня есть простая таблица, в которой хранятся уровни запасов.то есть.

ID int PK
LocationID int
StockLevel real

В этой таблице может быть несколько строк для каждого местоположения, т.е.:

ID | LocationID | StockLevel
----------------------------
1  |      1     | 100
2  |      1     | 124
3  |      2     | 300

В этом примере это тривиально, чтобы увидеть, что в местоположении 1 существует 224 единицы.

Когда я начинаю уменьшать уровень запаса в местоположении 1, я использую курсор, чтобы перебрать все строки, где LocationID равен 1, и с помощью некоторой простой логики решить, будет ли запас, доступный в текущей строке, удовлетворять переданному в уменьшениизначение.Если в строке есть достаточное количество для удовлетворения требования, я уменьшаю значение строки и вырываю курсор, и завершаю процедуру, однако, если в строке недостаточно доступного количества, я уменьшаю ее значение до нуля и перехожу к следующей строке и пытаюсьснова (с уменьшенным количеством)

Это довольно просто и работает нормально, но неизбежный вопрос: есть ли способ выполнить эту операцию RBAR без курсора?Я пытался искать альтернативы, но даже формулировка критериев поиска для такой операции является болезненной!

Заранее спасибо Ник

пс.Я храню данные в этом формате, потому что каждая строка также содержит другие столбцы, которые являются уникальными, и, следовательно, не могут быть просто объединены в одну строку для каждого местоположения.

pps.Логика курсора по запросу (где '@DecrementStockQuantityBy' - это количество, на которое нам нужно снизить уровень запаса в указанном месте):

WHILE @@FETCH_STATUS = 0
BEGIN

   IF CurrentRowStockStockLevel >= @DecrementStockQuantityBy
   BEGIN

          --This row has enough stock to satisfy decrement request
        --Update Quantity on the Current Row by @DecrementStockQuantityBy   
          --End Procedure       
          BREAK

   END

   IF CurrentRowStockStockLevel < @DecrementStockQuantityBy
   BEGIN

         --Update CurrentRowStockStockLevel to Zero
         --Reduce @DecrementStockQuantityBy by CurrentRowStockStockLevel
         --Repeat until @DecrementStockQuantityBy is zero or end of rows reached

   END

   FETCH NEXT FROM Cursor

END

Надеюсь, это достаточно ясно?Дайте мне знать, если требуется дальнейшее / лучшее объяснение.Спасибо

1 Ответ

0 голосов
/ 14 июля 2011

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

После более глубокого изучения вашего вопроса я также предложу альтернативное решение:

Declare @LocationValue int = 1,@decimentvalue int = 20


with temp (id,StockLevel,remaining) as (
select top 1 id, Case when StockLevel - @decimentvalue >0 then
           StockLevel = StockLevel - @decimentvalue 
         else 
           StockLevel = 0
         end,  @decimentvalue - StockLevel
from simpleTable st
where st.LocationID  = @LocationValue
union all 
select top 1 id, Case when StockLevel - t.remaining >0 then
           StockLevel = StockLevel -t.remaining 
         else 
           StockLevel = 0
         end,  t.remaining - StockLevel
from simpleTable st
where st.LocationID  = @LocationValue
and exists (select remaining from temp t
            where st.id <> t.id
            group by t.id
            having min(remaining ) >0) )

update st
set st.StockLevel = t.StockLevel
from simpleTable st
inner join temp t on t.id = st.id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...