[英]SQL Server - Set Based Waterfall
我有一個表,用於在不同的存儲桶(存儲桶1、2和3)中存儲數字余額。 在系統中過帳金額后,必須將金額分配到存儲桶。 事務類型決定了它如何影響存儲桶。 類型1、2和3增加相應的存儲桶(無瀑布),而類型0使用瀑布減少存儲桶。 這意味着類型0的數量首先減少存儲區1,然后任何剩余的存儲區減少存儲區2,任何剩余的存儲區減少存儲區3。
我目前使用一個游標應用金額,該游標遍歷每個已過帳的金額。 由於瀑布的緣故,關鍵是要應用的金額順序。 顯然,在處理成千上萬的金額時,它相當慢。 我想知道是否有基於集合的方法來執行此操作?
生成表和記錄的代碼:
我的分配數量的光標如下:
DECLARE @Instrument int,
@Type int,
@Amount numeric(19,2),
@NewAmount numeric(19,2),
@Seq int,
@Bucket1 numeric(19,2),
@Bucket2 numeric(19,2),
@Bucket3 numeric(19,2)
DECLARE Waterfall CURSOR Fast_Forward FOR
SELECT InstrumentID, TypeID, Amount, Sequence
FROM Amount
WHERE EffectiveDate between '2015-06-20' and '2015-06-30'
ORDER BY InstrumentID, Sequence
OPEN Waterfall;
FETCH NEXT from Waterfall into @Instrument, @Type, @Amount, @Seq
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @Bucket1 = Bucket1, @Bucket2 = Bucket2, @Bucket3 = Bucket3
FROM Buckets WHERE InstrumentID = @Instrument
IF @Type > 0 /*Increase Buckets, no waterfall*/
BEGIN
SET @Bucket1 = CASE WHEN @Type = 1 THEN @Bucket1 + @Amount ELSE @Bucket1 END
SET @Bucket2 = CASE WHEN @Type = 2 THEN @Bucket2 + @Amount ELSE @Bucket2 END
SET @Bucket3 = CASE WHEN @Type = 3 THEN @Bucket3 + @Amount ELSE @Bucket3 END
END
ELSE /*Decrease buckets with waterfall*/
BEGIN
SET @NewAmount = CASE WHEN @Amount >= @Bucket1 THEN @Amount - @Bucket1 ELSE 0 END
SET @Bucket1 = CASE WHEN @Amount >= @Bucket1 THEN 0 ELSE @Bucket1 - @Amount END
SET @Amount = @NewAmount
SET @NewAmount = CASE WHEN @Amount >= @Bucket2 THEN @Amount - @Bucket2 ELSE 0 END
SET @Bucket2 = CASE WHEN @Amount >= @Bucket2 THEN 0 ELSE @Bucket2 - @Amount END
SET @Amount = @NewAmount
SET @Bucket3 = CASE WHEN @Amount >= @Bucket3 THEN 0 ELSE @Bucket3 - @Amount END
END
/*Record effect of each amount on the balances for audit/undo*/
UPDATE Amount
SET Bucket1 = @Bucket1 - Buckets.Bucket1,
Bucket2 = @Bucket2 - Buckets.Bucket2,
Bucket3 = @Bucket3 - Buckets.Bucket3
FROM Buckets
inner join Amount
on Amount.InstrumentID = Buckets.InstrumentID
where Sequence = @Seq
/*update bucket values in table*/
UPDATE Buckets
SET Bucket1 = @Bucket1,
Bucket2 = @Bucket2,
Bucket3 = @Bucket3
WHERE InstrumentID = @Instrument
FETCH NEXT from Waterfall INTO @Instrument, @Type, @Amount, @Seq
END
CLOSE Waterfall
DEALLOCATE Waterfall
創建和插入腳本位於PasteBin,因為這樣,當包含它們時,我不會讓我發布問題(文本長度?)。
清楚說明瀑布序列至關重要的示例:
從以下內容開始:
Instrument | Bucket1 | Bucket2 | Bucket 3
1 | 500 | 200 | 3000
如下適用兩個數額
Instrument | Sequence| Type | Amount
1 | 1 | 0 | 800 /*this decreases buckets via waterfall*/
1 | 2 | 1 | 500 /*this increases bucket 1*/
如果按順序應用金額,則結果如下:
Instrument | Bucket1 | Bucket2 | Bucket 3
1 | 500 | 0 | 2900
但是,金額按相反順序應用,結果不正確:
Instrument | Bucket1 | Bucket2 | Bucket 3
1 | 200 | 200 | 3000
這樣的東西就是您想要的。 比CURSOR
效率要高得多。
UPDATE
b
SET
Bucket1 = CASE WHEN a.[Type] = 1 THEN b.Bucket1 + a.Amount
WHEN a.[Type] = 0 AND Amount >= b.Bucket1 THEN 0
WHEN a.[Type] = 0 AND Amount < b.Bucket1 THEN b.Bucket1 - a.Amount
ELSE Bucket1
END,
Bucket2 = CASE WHEN a.[Type] = 2 THEN b.Bucket2 + a.Amount
WHEN a.[Type] = 0 AND Amount >= b.Bucket1 + Bucket2 THEN 0
WHEN a.[Type] = 0 AND Amount BETWEEN b.Bucket1 AND Bucket2 THEN Bucket2 - (a.Amount - b.Bucket1)
ELSE Bucket2
END,
Bucket3 = CASE WHEN a.[Type] = 3 THEN b.Bucket3 + a.Amount
WHEN a.[Type] = 0 AND Amount >= b.Bucket1 + Bucket2 THEN Bucket3 - (a.Amount - b.Bucket1 - Bucket2)
ELSE Bucket3
END
FROM
dbo.Buckets AS b
JOIN
(SELECT TOP 10000000 * FROM dbo.Amounts ORDER BY Sequence) AS a
ON b.InstrumentID = a.InstrumentID
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.