Reputation: 946
This is my table structure:
CREATE table Credit(id integer, organisationid int, availableCredit int)
INSERT INTO Credit VALUES (1, 1, 1000)
INSERT INTO Credit VALUES (2, 1, 100)
INSERT INTO Credit VALUES (3, 2, 600)
INSERT INTO Credit VALUES (4, 2, 400)
I have to reduce the available credit column value, I have amount 1050 with me. I need to reduce 1050 from credit table where organisation id = 1. Here the organisation Id 1 have 1100 available credit in total. The condition is the first inserted credit row should be updated first and then the rest (FIFO model), also the updation should happen only for organisationId = 1.
How do we update this using a single or multiple update statement?
Any suggestions?
Upvotes: 2
Views: 2841
Reputation: 13486
Previously I had given only select query,Here is the final UPDATE query which does the task.
DECLARE @balance int=1050
;WITH CTE as (
select id,organisationid,CASE when @balance>availableCredit then 0 else availableCredit-@balance end as availableCredit,
CASE when @balance>availableCredit then @balance-availableCredit else 0 end as balamt from Credit where id=1 and organisationid=1
union all
select t.id,t.organisationid,CASE when c.balamt>t.availableCredit then 0 else t.availableCredit-c.balamt end as availableCredit,
CASE when c.balamt>t.availableCredit then c.balamt-t.availableCredit else 0 end as balamt1
from Credit t inner join CTE c on t.id-1=c.id --and t.organisationid=1
)
Update c SET c.availableCredit = ct.availableCredit
FROM Credit c inner join CTE ct
on c.id=ct.id
SELECT * FROM Credit
Upvotes: 1
Reputation: 13486
Try This query:
CREATE table Credit(id integer, organisationid int, availableCredit int)
INSERT INTO Credit VALUES (1, 1, 1000)
INSERT INTO Credit VALUES (2, 1, 100)
INSERT INTO Credit VALUES (3, 2, 600)
INSERT INTO Credit VALUES (4, 2, 400)
DECLARE @balance int=1050
;WITH CTE as (
select id,organisationid,CASE when @balance>availableCredit then 0 else availableCredit-@balance end as availableCredit,
CASE when @balance>availableCredit then @balance-availableCredit else 0 end as balamt from Credit where id=1 and organisationid=1
union all
select t.id,t.organisationid,CASE when c.balamt>t.availableCredit then 0 else t.availableCredit-c.balamt end as availableCredit,
CASE when c.balamt>t.availableCredit then c.balamt-t.availableCredit else 0 end as balamt1
from Credit t inner join CTE c on t.id-1=c.id and t.organisationid=1
)
SELECT id,organisationid,availableCredit FROM CTE
Upvotes: 0
Reputation: 754240
Unfortunately, this is a rather messy thing to do in T-SQL - you'll need something like a loop (cursor or WHILE
statement).
With this code here, I can get it to run - it's not pretty, but it works.
-- you want to reduce the total credits by this amount
DECLARE @AmountToReduce INT = 1050
-- temporary variables
DECLARE @ID INT, @AvailableCredit INT
-- get the first row from dbo.Credit that still has availableCredit - ordered by id
SELECT TOP 1 @ID = id, @AvailableCredit = availableCredit
FROM dbo.Credit
WHERE availableCredit > 0 AND organisationId = 1
ORDER BY id
-- as long as we still have credit to reduce - loop..
WHILE @AmountToReduce > 0 AND @ID IS NOT NULL
BEGIN
-- if we need to remove the complete availableCredit - do this UPDATE
IF @AmountToReduce > @AvailableCredit
BEGIN
UPDATE dbo.Credit
SET availableCredit = 0
WHERE id = @ID
SET @AmountToReduce = @AmountToReduce - @AvailableCredit
END
ELSE BEGIN
-- if the amount to reduce left is less than the availableCredit - do this UPDATE
UPDATE dbo.Credit
SET availableCredit = availableCredit - @AmountToReduce
WHERE id = @ID
SET @AmountToReduce = 0
END
-- set @ID to NULL to be able to detect that there's no more rows left
SET @ID = NULL
-- select the next "first" row with availableCredit > 0 to process
SELECT TOP 1 @ID = id, @AvailableCredit = availableCredit
FROM dbo.Credit
WHERE availableCredit > 0 AND organisationId = 1
ORDER BY id
END
Upvotes: 2
Reputation: 103338
This script reduces "Id 1" availableCredit
by 1000, and reduces "Id 2" availableCredit
by 50.
UPDATE Credit
SET availableCredit=(availableCredit-1000)
WHERE id=1
UPDATE Credit
SET availableCredit=(availableCredit-50)
WHERE id=2
Upvotes: 1