2

这是我的表结构:

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)

我必须减少可用的信用列值,我有 1050 的金额。我需要从组织 ID = 1 的信用表中减少 1050。这里的组织 ID 1 总共有 1100 个可用信用。条件是应该先更新第一个插入的信用行,然后再更新其余的(FIFO 模型),而且更新应该只发生在 organizationId = 1 的情况下。

我们如何使用单个或多个更新语句来更新它?

有什么建议么?

4

4 回答 4

2

不幸的是,这在 T-SQL 中是一件相当麻烦的事情——你需要像循环(游标或WHILE语句)这样的东西。

有了这里的代码,我可以让它运行——它不漂亮,但它可以工作。

-- 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
于 2012-07-25T10:51:35.507 回答
1

此脚本将“Id 1”availableCredit减少 1000,并将“Id 2”availableCredit减少 50。

UPDATE Credit
SET availableCredit=(availableCredit-1000)
WHERE id=1

UPDATE Credit
SET availableCredit=(availableCredit-50)
WHERE id=2
于 2012-07-25T10:40:46.853 回答
1

以前我只给出了选择查询,这是完成该任务的最终 UPDATE 查询。

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 
于 2012-07-26T04:22:22.330 回答
0

试试这个查询:

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
于 2012-07-25T12:11:55.847 回答