我有一个表,将数字余额存储在不同的存储桶(存储桶 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