I have a simple table that stores stock levels. ie.
ID int PK
LocationID int
StockLevel real
There could be multiple rows in this table for each location ie:
ID | LocationID | StockLevel
----------------------------
1 | 1 | 100
2 | 1 | 124
3 | 2 | 300
In this example its trivial to see that 224 units exist at location 1.
When I come to decrement the stock level at location 1 I am using a cursor to iterate over all rows at where LocationID is 1 and using some simple logic decide whether the stock available at the current row will satisfy the passed in decrement value. If the row has sufficient quantity to satisfy the requirement I decrement the rows value and break out of the cursor, and end the procedure, however if the row doesnt have sufficient quantity available I decrement its value to zero and move to the next row and try again (with the reduced quantity)
Its quite simple and works ok, but the inevitable question is: Is there a way of performing this RBAR operation without a cursor?? I have attempted to search for alternatives but even wording the search criteria for such an operation is painful!
Thanks in advance Nick
ps. I am storing data in this format because each row also contains other columns that are unique, and hence cant simply be aggregated into one row for each location.
pps. Cursor Logic as requested (where '@DecrementStockQuantityBy' is the quantity that we need to reduce the stock level by at the specified location):
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开发者_StackOverflow CurrentRowStockStockLevel to Zero
--Reduce @DecrementStockQuantityBy by CurrentRowStockStockLevel
--Repeat until @DecrementStockQuantityBy is zero or end of rows reached
END
FETCH NEXT FROM Cursor
END
Hope this is clear enough? Let me know if further/better explanation is required. Thanks
You are correct sir a simple update statement can help you in this scenario I'm still trying to find a legitimate use for a cursor or while that I can't solve with CTE or set based.
After looking a little deeper into your question I will also propose an alternate solution:
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
精彩评论