If you are using SQL 2012, you can use the following:
DECLARE @PayAmount INT = 900; WITH Dues AS ( SELECT *, Total-Paid AS Due FROM Bill ) , Cumulative AS ( SELECT *, SUM(Due) OVER (ORDER BY Id) AS CumulativeTotalDue FROM Dues ) , Payable AS ( SELECT *, @PayAmount - CumulativeTotalDue AS AmountLeftAfterPaying FROM Cumulative ) , BillWithAmountToApplyRaw AS ( SELECT * , CASE WHEN AmountLeftAfterPaying >= 0 THEN Due ELSE Due + AmountLeftAfterPaying END AS RawAmountToApply FROM Payable ) , BillWithAmountToApply AS ( SELECT *, CASE WHEN RawAmountToApply < 0 THEN 0 ELSE RawAmountToApply END AS AmountToApply FROM BillWithAmountToApplyRaw )
This will give you the amount to be applied in the AmountToApply column. So you can use the above as
UPDATE BillWithAmountToApply SET Paid = Paid + AmountToApply FROM BillWithAmountToApply
(Use
SELECT * FROM BillWithAmountToApply
to check it out if you want)
SQL 2008 version (less efficient due to repeated joins that are not needed in 2012):
WITH Dues AS ( SELECT *, Total-Paid AS Due FROM Bill ) , CumulativeDue AS ( SELECT base.Id, SUM(cumulative.Due) AS CumulativeTotalDue FROM Dues base JOIN Dues cumulative ON cumulative.Id <= base.Id GROUP BY base.Id ) , Cumulative AS ( SELECT Dues.*, CumulativeDue.CumulativeTotalDue FROM Dues JOIN CumulativeDue ON CumulativeDue.Id = Dues.Id ) ... as above
Schema Objects:
--BEGIN TRAN; --CREATE TABLE Bill --( -- ID Int PRIMARY KEY IDENTITY, -- Total INT NOT NULL, -- Paid INT NOT NULL DEFAULT(0), -- Status AS -- CASE -- WHEN Paid = Total THEN 'Paid' -- WHEN Paid = 0 THEN 'Unpaid' -- ELSE 'Part Paid' -- END --); --WITH KnownValues(Total, Paid) AS --( -- SELECT 1000, 1000 -- UNION ALL SELECT 500, 400 -- UNION ALL SELECT 700, 0 -- UNION ALL SELECT 200, 0 --) --INSERT INTO Bill(Total, Paid) --SELECT * --FROM KnownValues; --COMMIT