Немного грязно, но вот что я придумал:
Код для настройки ваших базовых таблиц ...
-- setup code
CREATE TABLE #tmp (
[NO] int identity(1,1),
[TRAN] money,
[REFUND] money
)
INSERT #tmp VALUES (100, 0)
INSERT #tmp VALUES (200, 0)
INSERT #tmp VALUES (300, 0)
Код для добавления суммы возврата ...
DECLARE @amt money SET @amt = 50
UPDATE u
SET REFUND =
CASE WHEN u.[REFUND] = u.[TRAN] THEN u.[REFUND] --'already full - do nothing'
WHEN cumulativepretran >= aiming_for_ref THEN u.[REFUND] --'after all - do nothing'
WHEN cumulativetran + cumulativeref > ((totalref + @amt) - u.[TRAN]) THEN (totalref + @amt + u.[REFUND]) - (cumulativeref) --'calc'
ELSE u.[TRAN] END -- 'fill-er-up'
FROM #tmp u
INNER JOIN (SELECT *,
ISNULL((select sum([REFUND]) FROM #tmp WHERE [NO] <= t.[NO]), 0) 'cumulativeref',
ISNULL((select sum([TRAN]) FROM #tmp WHERE [NO] <= t.[NO]), 0) 'cumulativetran',
ISNULL((select sum([REFUND]) FROM #tmp WHERE [NO] < t.[NO]), 0) 'cumulativepreref',
ISNULL((select sum([TRAN]) FROM #tmp WHERE [NO] < t.[NO]), 0) 'cumulativepretran',
ISNULL((select sum([REFUND]) FROM #tmp), 0) 'totalref',
ISNULL((select sum([REFUND]) FROM #tmp), 0) + @amt 'aiming_for_ref'
FROM #tmp t) as m ON m.[NO] = u.[NO]