开发者

Reducing values in one table until reserves depleted in another - recursion?

I have two tables - let's call them dbo.ValuesToReduce and dbo.Reserve The data in the first table (dbo.ValuesToReduce) is:

ValuesToReduceId | PartnerId | Value
-------------------------------------
1                | 1         | 53.15
2                | 2         | 601.98
3                | 1         | 91.05
4                | 2         | 44.56
5                | 3         | 19.11

The second table (dbo.Reserve) 开发者_StackOverflow中文版looks like this

ReserveId | PartnerId | Value
-------------------------------
1         | 1         | -101.55
2         | 2         | -425.19
3         | 3         | -28.17

What I need to do is: update the Values in ValuesToReduce table using the latter table of Reserves, reducing the numbers until the reserve supply is exhausted. Here's what I should get after running the script:

ValuesToReduceId | PartnerId | Value
-------------------------------------
1                | 1         | 0.00
2                | 2         | 176.79
3                | 1         | 42.65
4                | 2         | 44.56
5                | 3         | 0.00


ReserveId | PartnerId | Value
-------------------------------
1         | 1         | 0.00
2         | 2         | 0.00
3         | 3         | -9.06

So basically, every partner has a "reserve" which he can deplete, and values in the value table should be reduced by partner accordingly if there is still something in the reserves. Reserves should be collocated in the order provided by ValuesToReduceId.

For partner with PartnerId of 1, you can see that he had enough reserve to update his first value to 0 and still had some left to reduce the second value by that amount.

Partner with ID of 2 had a reserve of 425.19, and there were two entries in the values table for that partner, 601.98 and 44.56, in that order (by ValuesToReduceId), so we only updated the first value since the reserve is not big enough for both. The wrong way would have been to update the second value to 0.00 and the first to 221.35.

Partner with ID of 3 has more than enough reserve, so after updating his value to 0, he's left with -9.06

I tried something with recursive cte, but I can't seem to get my head around it. Hope I described the problem clearly enough..


You cannot, as far as I know, update two tables in a single select statement.

But you could do this in SQL using a WHILE loop. Search for the first transaction, then carry it out, until there are no possible transactions left.

declare @valid int
declare @resid int
declare @val float
while 1 = 1
    begin

    select top 1 
      @resid = r.ReserveId
    , @valid = v.ValuesToReduceId
    , @val = CASE WHEN -r.Value > v.Value THEN v.Value ELSE -r.Value END
    from ValuesToReduce v
    inner join Reserves r on r.PartnerId = v.PartnerId
    where r.Value < 0 and v.Value > 0
    order by r.ReserveId

    if @@rowcount = 0
        break

    update ValuesToReduce 
    set Value = Value - @val 
    where ValuesToReduceId = @valid

    update Reserves 
    set Value = Value + @val 
    where ReserveId = @resid
    end

Here's code to create test tables:

create table ValuesToReduce (
    ValuesToReduceId int,
    PartnerId int,
    Value float
)

insert into ValuesToReduce values (1,1,53.15)
insert into ValuesToReduce values (2,2,601.98)
insert into ValuesToReduce values (3,1,91.05)
insert into ValuesToReduce values (4,2,44.56)
insert into ValuesToReduce values (5,3,19.11)

create table Reserves (
    ReserveId int,
    PartnerId int,
    Value float
)

insert into Reserves values  (1,1,-101.55)
insert into Reserves values (2,2,-425.19)
insert into Reserves values (3,3,-28.17)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜