SQL Server查询:调整钱栏

时间:2015-10-30 13:37:40

标签: sql sql-server tsql sql-server-2012

我试图在没有游标的情况下进行以下操作。有可能吗?

我有这个变量:

DECLARE @Amount MONEY = 800;

我目前的样本表:

EntryID    Amount
--------------------------------------------
1       200
2       250
3       600
4       100
...     ....(could be many more rows)

我希望能够更新表格,只显示" Amount"它需要加起来@Amount变量($ 800)。所以我希望桌子能像这样结束:

EntryID    Amount
--------------------------------------------
1       200 (uses up full 200)
2       250 (uses up full 250)
3       350 (uses up 350 of the 600)

或者就像这样

EntryID    Amount     Distrib
--------------------------------------------
1       200        200
2       250        250
3       600        350
4       100        0
...     ...            ...

因此SUM()等于@Amount

提前致谢!

PS - 我在SQL Server 2012中这样做

更新

这是我的最终解决方案。再次感谢,戈登:

DECLARE @Amount money = 800;
DECLARE @tmpPaymentDist TABLE (EntryID INT, Amount MONEY, Distrib MONEY);

INSERT INTO @tmpPaymentDist (EntryID, Amount) VALUES (1, 200);
INSERT INTO @tmpPaymentDist (EntryID, Amount) VALUES (2, 250);
INSERT INTO @tmpPaymentDist (EntryID, Amount) VALUES (3, 600);
INSERT INTO @tmpPaymentDist (EntryID, Amount) VALUES (4, 100);

with toupdate as (
    select t.*,
        (case when sum(amount) over (order by entryid) <= @amount
        then amount
        when sum(amount) over (order by entryid) < @amount + amount
        then @amount - (sum(amount) over (order by entryid) - amount)
        else 0
    end) as new_distrib
    from @tmpPaymentDist t
)

update T set distrib = new_distrib 
FROM @tmpPaymentDist T
INNER JOIN toupdate T2 ON T2.EntryID = T.EntryID
WHERE T2.new_distrib > 0

SELECT * FROM @tmpPaymentDist

1 个答案:

答案 0 :(得分:3)

是的,你可以使用累积总和而无需游标:

select t.*,
       (case when sum(amount) over (order by entryid) <= @amount
             then amount
             when sum(amount) over (order by entryid) < @amount + amount
             then @amount - (sum(amount) over (order by entryid) - amount)
             else 0
        end) as distrib
from table t;

即,使用累计金额进行计算。

对于update,您可以使用相同的逻辑:

with toupdate as (
      select t.*,
             (case when sum(amount) over (order by entryid) <= @amount
                   then amount
                   when sum(amount) over (order by entryid) < @amount + amount
                   then @amount - (sum(amount) over (order by entryid) - amount)
                   else 0
              end) as new_distrib
      from table t
     )
update toudpate
    set distrib = new_distrib;