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 モデル) が更新され、組織 ID = 1 に対してのみ更新が行われることです。

単一または複数の update ステートメントを使用してこれを更新するにはどうすればよいでしょうか?

助言がありますか?

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

以前はselectクエリのみを指定していましたが、これがタスクを実行する最後の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 に答える
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 に答える
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 に答える