Если в ваших индексах нет пробелов, простейшим решением будет
- Создать рекурсив
CTE
, начиная со значения для вычитания и уменьшения его в рекурсивной части.
- Используйте результаты
CTE
для обновления вашей фактической таблицы
Оператор SQL
;WITH q AS (
SELECT idx, amount, balance, 130 AS Deduct
FROM tbl1
WHERE idx = 1
UNION ALL
SELECT t.idx, t.amount, t.balance, q.Deduct - q.balance
FROM q
INNER JOIN @tbl1 t ON t.idx = q.idx + 1
WHERE q.Deduct - q.balance > 0
)
UPDATE @tbl1
SET Balance = CASE WHEN q.Balance - q.Deduct > 0 THEN q.Balance - q.Deduct ELSE 0 END
FROM q
INNER JOIN tbl1 t ON t.idx = q.idx
Используя ROW_NUMBER
, вы можете облегчить проблему с пропуском, но это немного усложнит запрос.
;WITH r AS (
SELECT idx, amount, balance, rn = ROW_NUMBER() OVER (ORDER BY idx)
FROM tbl1
), q AS (
SELECT rn, amount, balance, 130 AS Deduct, idx
FROM r
WHERE rn = 1
UNION ALL
SELECT r.rn, r.amount, r.balance, q.Deduct - q.balance, r.idx
FROM q
INNER JOIN r ON r.rn = q.rn + 1
WHERE q.Deduct - q.balance > 0
)
UPDATE tbl1
SET Balance = CASE WHEN q.Balance - q.Deduct > 0 THEN q.Balance - q.Deduct ELSE 0 END
FROM q
INNER JOIN @tbl1 t ON t.idx = q.idx
Тестовый скрипт
DECLARE @tbl1 TABLE (idx INTEGER, Amount INTEGER, Balance INTEGER)
INSERT INTO @tbl1 (idx,amount,balance) VALUES (1, 50, 50)
INSERT INTO @tbl1 (idx,amount,balance) VALUES (2, 30, 30)
INSERT INTO @tbl1 (idx,amount,balance) VALUES (3, 20, 20)
INSERT INTO @tbl1 (idx,amount,balance) VALUES (4, 50, 50)
INSERT INTO @tbl1 (idx,amount,balance) VALUES (5, 60, 60)
;WITH q AS (
SELECT idx, amount, balance, 130 AS Deduct
FROM @tbl1
WHERE idx = 1
UNION ALL
SELECT t.idx, t.amount, t.balance, q.Deduct - q.balance
FROM q
INNER JOIN @tbl1 t ON t.idx = q.idx + 1
WHERE q.Deduct - q.balance > 0
)
UPDATE @tbl1
SET Balance = CASE WHEN q.Balance - q.Deduct > 0 THEN q.Balance - q.Deduct ELSE 0 END
FROM q
INNER JOIN @tbl1 t ON t.idx = q.idx
SELECT *
FROM @tbl1
выход
idx Amount Balance
1 50 0
2 30 0
3 20 0
4 50 20
5 60 60