SQL-使用参考表将值拆分为存储桶

问题描述 投票:1回答:1

我试图描述以下挑战;但是也许理解的[[best方法可能是运行示例SQL并从示例输出表(@IncomingSplitBucket)中向后工作

我敢肯定,有一种雄辩的方式来编写代码,但这超出了我的最大努力。

挑战题为:

将数字拆分为存储桶

每个客户都有付款桶(@bucket)。我希望在付款时将付款分配到存储桶中,请参见表格(@incoming)。

付款可以跨越存储桶,并且可以为+/-金额。

使用(@incoming)和(@buckets)信息-AIM会将付款分配到存储桶中。当付款金额超过存储桶金额时,应拆分付款。

表@IncomingSplitBucket –提供所需的输出。理解需求的一种方法是也许对此有所了解,然后倒退。

我已经尝试过许多解决此问题的方法,但均失败了。

/* Please run code and review */ --=========================================== --t1 - PAYMENT SCHEDULE SPLIT INTO BUCKET --=========================================== DECLARE @bucket TABLE ( CustID INT, BucketSeqID char(1), Amount money ) INSERT INTO @bucket SELECT 1,'a', '1000' union SELECT 1,'b', '1000' union SELECT 1,'c', '2000' union SELECT 1,'d', '2000' union SELECT 2,'a', '5000'union SELECT 2,'b', '5000'union SELECT 2,'c', '1000'union SELECT 2,'d', '1000'union SELECT 3,'a', '5000' union SELECT 3,'b', '5000' --=========================================== --t2 - PAYMENTS COMING IN --=========================================== DECLARE @incoming TABLE ( CustID INT, IncomingSeqID INT, Amount money ) INSERT INTO @incoming SELECT 1,1, '1000' union SELECT 1,2, '2000' union SELECT 1,3, '3000' union SELECT 2,1, '5000' union SELECT 2,2, '3000' union SELECT 2,3, '2000' union SELECT 2,4, '2000' union SELECT 3,1, '3000' union SELECT 3,2, '3000' union SELECT 3,3, '3000' union SELECT 3,4, '1000' --================================================================= --t3 - THIS IS WHAT THE OUTPUT DATA SHOULD LOOK LIKE --================================================================ DECLARE @IncomingSplitBucket TABLE ( CustID INT, IncomingSeqID INT, BucketSeqID char(1), AmountBucket money ) INSERT INTO @IncomingSplitBucket SELECT 1,1,'a','1000' union SELECT 1,2,'b','1000' union SELECT 1,2,'c','1000' union SELECT 1,3,'c','1000' union SELECT 1,3,'d','2000' union SELECT 2,1,'a','5000' union SELECT 2,2,'b','3000' union SELECT 2,3,'b','2000' union SELECT 2,4,'c','1000' union SELECT 2,4,'d','1000' union SELECT 3,1,'a','3000' union SELECT 3,2,'a','2000' union SELECT 3,2,'b','1000' union SELECT 3,3,'b','3000' union SELECT 3,4,'b','1000' --================================================================= --Outputs and Data Checks --================================================================ --REVIEW DATA select * from @bucket select * from @incoming select * from @IncomingSplitBucket --(sample output) --DATA Check - The SUM AmountBucket of Grouped BucketSeqID = the @bucket amounts see table SELECT CustID, BucketSeqID, SUM(AmountBucket) AS BucketCheck FROM @IncomingSplitBucket GROUP BY CustID, BucketSeqID order by 1,2 --DATA Check - The SUM AmountBucket of Grouped IncomingSeqID = the @incoming amounts see table SELECT CustID, IncomingSeqID, SUM(AmountBucket) AS BucketCheck FROM @IncomingSplitBucket GROUP BY CustID, IncomingSeqID order by 1,2

sql tsql bucket
1个回答
0
投票
首先,我将使用通用表表达式(cte)来更改列名,因此我在表之间没有相似的列名以简化我们的生活,此外,还将存储区名称a,b,c,d转换为seq 1 ,2,3,4为简单起见。

然后,我将继续使用另一个递归cte来获取第一个存储桶和第一个收款,如果该存储桶未填充下一条记录,我将使用相同的未填充存储桶,否则我将使用下一个存储桶,如果收款正好适合下一行存储桶的其余部分,我将转到下一笔付款;否则,我将使用其余的收款直到所有收款都完成。

请参阅下面的CTE

;with bucket as ( select CustID BucketCustID,BucketSeqID, case BucketSeqID when 'a' then 1 when 'b' then 2 when 'c' then 3 when 'd' then 4 end BucketSeq ,Amount bucketAmount from @bucket ),incoming as ( select CustID IncomingCustID, IncomingSeqID ,Amount [IncomingAmount] from @incoming ),result as ( select BucketCustID,IncomingSeqID,BucketSeqID,BucketSeq ,case when bucketAmount<IncomingAmount then 0 else bucketAmount-IncomingAmount end bucketAmount ,case when bucketAmount>IncomingAmount then 0 else IncomingAmount-bucketAmount end IncomingAmount ,case when bucketAmount>IncomingAmount then IncomingAmount else bucketAmount end InBucket from bucket b inner join incoming i on i.IncomingCustID=b.BucketCustID and i.IncomingSeqID=1 where b.BucketSeq=1 union all select BucketCustID,IncomingSeqID,BucketSeqID,BucketSeq ,case when bucketAmount<IncomingAmount then 0 else bucketAmount-IncomingAmount end bucketAmount ,case when bucketAmount>IncomingAmount then 0 else IncomingAmount-bucketAmount end IncomingAmount ,case when bucketAmount>IncomingAmount then IncomingAmount else bucketAmount end InBucket from ( select b.BucketCustID,i.IncomingSeqID,b.BucketSeqID,b.BucketSeq ,case when r.BucketSeq=b.BucketSeq then r.bucketAmount else b.bucketAmount end bucketAmount ,case when r.IncomingSeqID=i.IncomingSeqID then r.IncomingAmount else i.IncomingAmount end IncomingAmount from result r inner join bucket b on b.BucketCustID=r.BucketCustID and b.BucketSeq=r.BucketSeq+(case when r.bucketAmount=0 then 1 else 0 end) inner join incoming i on i.IncomingCustID=r.BucketCustID and i.IncomingSeqID=r.IncomingSeqID+(case when r.IncomingAmount=0 then 1 else 0 end) ) Prev ) select BucketCustID CustID,IncomingSeqID,BucketSeqID,InBucket AmountBucket from result r order by BucketCustID,IncomingSeqID,BucketSeqID

输出与您期望的输出匹配,如下所示:-

CustID IncomingSeqID BucketSeqID AmountBucket 1 1 a 1000.00 1 2 b 1000.00 1 2 c 1000.00 1 3 c 1000.00 1 3 d 2000.00 2 1 a 5000.00 2 2 b 3000.00 2 3 b 2000.00 2 4 c 1000.00 2 4 d 1000.00 3 1 a 3000.00 3 2 a 2000.00 3 2 b 1000.00 3 3 b 3000.00 3 4 b 1000.00

© www.soinside.com 2019 - 2024. All rights reserved.