Я думаю, что эту проблему можно решить, используя подход, основанный исключительно на множествах.
В основном вам необходимо выполнить следующие шаги:
Получить таблицу доступных в настоящее времяколичество для каждого элемента.
Получите промежуточные суммы из заказанного количества, подлежащего обработке.
Получите QtyAvailableAfterAllocation
для каждого элемента какрезультат вычитания его промежуточного итога из его доступного количества.
Вот пример решения:
/* sample data definition & initialisation */
DECLARE @LastQty TABLE (Item int, Qty int);
INSERT INTO @LastQty (Item, Qty)
SELECT 0123, 404 UNION ALL
SELECT 1234, 505 UNION ALL
SELECT 2345, 606 UNION ALL
SELECT 3456, 707 UNION ALL
SELECT 4567, 808 UNION ALL
SELECT 5678, 909;
DECLARE @Orders TABLE (ID int, Item int, OrderedQty int);
INSERT INTO @Orders (ID, Item, OrderedQty)
SELECT 1, 1234, 5 UNION ALL
SELECT 2, 1234, 15 UNION ALL
SELECT 3, 2345, 3 UNION ALL
SELECT 4, 1234, 10 UNION ALL
SELECT 5, 2345, 37 UNION ALL
SELECT 6, 2345, 45 UNION ALL
SELECT 7, 3456, 50 UNION ALL
SELECT 8, 4567, 25 UNION ALL
SELECT 9, 2345, 30;
/* the actuall query begins here */
WITH RankedOrders AS (
SELECT
*,
rn = ROW_NUMBER() OVER (PARTITION BY Item ORDER BY ID)
FROM @Orders
),
RunningOrderTotals AS (
SELECT
ID,
Item,
OrderedQty,
RunningTotalQty = OrderedQty,
rn
FROM RankedOrders
WHERE rn = 1
UNION ALL
SELECT
o.ID,
o.Item,
o.OrderedQty,
RunningTotalQty = r.RunningTotalQty + o.OrderedQty,
o.rn
FROM RankedOrders o
INNER JOIN RunningOrderTotals r ON o.Item = r.Item AND o.rn = r.rn + 1
)
SELECT
t.ID,
t.Item,
t.OrderedQty,
QtyAvailableAfterAllocation = oh.Qty - t.RunningTotalQty
FROM RunningOrderTotals t
INNER JOIN @LastQty oh ON t.Item = oh.Item
ORDER BY t.ID;
Примечание. Для целей моего примера я инициализировалтаблица доступных позиций (@LastQty
) вручную.Тем не менее, вы, скорее всего, собираетесь извлечь его из ваших данных.