Sql 解决问题。我将不得不更详细地研究您的解决方案,但它似乎试图将所有付款的总和分配到可用的存储空间中。但是,需要的是每次付款都要填满存储桶(对于上面的付款2,存储桶存储量仍然是所有存储桶的总和)。对不起,这还不够清楚。不过,这是一个很好的解决方案。让我们看看我
Sql 解决问题。我将不得不更详细地研究您的解决方案,但它似乎试图将所有付款的总和分配到可用的存储空间中。但是,需要的是每次付款都要填满存储桶(对于上面的付款2,存储桶存储量仍然是所有存储桶的总和)。对不起,这还不够清楚。不过,这是一个很好的解决方案。让我们看看我,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,解决问题。我将不得不更详细地研究您的解决方案,但它似乎试图将所有付款的总和分配到可用的存储空间中。但是,需要的是每次付款都要填满存储桶(对于上面的付款2,存储桶存储量仍然是所有存储桶的总和)。对不起,这还不够清楚。不过,这是一个很好的解决方案。让我们看看我是否可以根据我的要求调整它(这样我可以将它的性能与@Gulli Meel的解决方案进行比较)。你完全正确,这确实是我理解你的问题的方式(将所有付款的总和分配到所有桶中)。对不起,我帮不上忙了。至于我,我很高兴解决了我读到你的问题,所以无论如何,
解决问题。我将不得不更详细地研究您的解决方案,但它似乎试图将所有付款的总和分配到可用的存储空间中。但是,需要的是每次付款都要填满存储桶(对于上面的付款2,存储桶存储量仍然是所有存储桶的总和)。对不起,这还不够清楚。不过,这是一个很好的解决方案。让我们看看我是否可以根据我的要求调整它(这样我可以将它的性能与@Gulli Meel的解决方案进行比较)。你完全正确,这确实是我理解你的问题的方式(将所有付款的总和分配到所有桶中)。对不起,我帮不上忙了。至于我,我很高兴解决了我读到你的问题,所以无论如何,谢谢你的问题。:)很高兴你没有觉得这是浪费时间
PaymentId Value BucketId MaxAmount
-------------------------- --------------------------------
1 16.5 1 5.5
2 7.0 2 10
3 8.3
DECLARE @Buckets TABLE (
BucketId INT,
MaxAmount DECIMAL(18,6)
)
INSERT INTO @Buckets VALUES (1, 5.5)
INSERT INTO @Buckets VALUES (2, 10)
INSERT INTO @Buckets VALUES (3, 8.3)
DECLARE @Payments TABLE (
PaymentId INT,
Value DECIMAL(18,6)
)
INSERT INTO @Payments VALUES (1,16.5)
INSERT INTO @Payments VALUES (2,7.0)
SELECT
P1.PaymentId
, P1.Value as TotalPayment
, B4.BucketId
, B4.MaxAmount
, CASE WHEN B3.BucketId = B4.BucketId THEN P1.Value - MaxAmountRunningTotalOfPreviousBuckets ELSE B4.MaxAmount END AS BucketPaymentAmount
FROM @Payments P1
INNER JOIN (
SELECT
B2.BucketId
, B2.MaxAmount as BucketMaxAmount
, SUM(B1.MaxAmount) - B2.MaxAmount as MaxAmountRunningTotalOfPreviousBuckets
FROM @Buckets B1
INNER JOIN @Buckets B2
ON B1.BucketId <= B2.BucketId
GROUP BY B2.BucketId, B2.MaxAmount
) AS B3
ON P1.Value > B3.MaxAmountRunningTotalOfPreviousBuckets AND P1.Value <= (B3.MaxAmountRunningTotalOfPreviousBuckets + BucketMaxAmount)
INNER JOIN @Buckets B4
ON B4.BucketId <= B3.BucketId
ORDER BY P1.PaymentId, B3.BucketId
DECLARE @Buckets TABLE (
BucketId INT,
MaxAmount DECIMAL(18,6)
)
INSERT INTO @Buckets VALUES (1, 5.5)
INSERT INTO @Buckets VALUES (2, 10)
INSERT INTO @Buckets VALUES (3, 8.3)
DECLARE @Payments TABLE (
PaymentId INT,
Value DECIMAL(18,6)
)
INSERT INTO @Payments VALUES (1,16.5)
INSERT INTO @Payments VALUES (2,7.0)
INSERT INTO @Payments VALUES (3,23.8)
DECLARE @tempBuckets TABLE (
BucketId INT,
MaxAmount DECIMAL(18,6) ,
currentruntotal decimal(18,6)
)
insert into @tempBuckets select bucketid,maxamount ,(select SUM(maxamount) from @Buckets bin where b.bucketid >=bin.bucketid)
--,isnull((select SUM(maxamount) from @Buckets bin where b.bucketid > bin.bucketid),0)
from @Buckets b
select * from @tempBuckets
select PaymentId,Value,BucketId,
case when p.Value >= tb.currentruntotal then tb.MaxAmount else p.Value - tb.currentruntotal + tb.MaxAmount end as bucketamount
from @Payments p inner join @tempBuckets tb on (p.Value >= tb.currentruntotal or p.Value between tb.currentruntotal - tb.MaxAmount and tb.currentruntotal )
order by PaymentId
go
WITH BucketsRanked AS (
SELECT *, rnk = ROW_NUMBER() OVER (ORDER BY BucketId) FROM Buckets
)
, PaymentsRanked AS (
SELECT *, rnk = ROW_NUMBER() OVER (ORDER BY PaymentId) FROM Payments
)
, PaymentsDistributed AS (
SELECT
b.BucketId,
p.PaymentId,
Bucket = b.MaxAmount,
Payment = p.Value,
BucketRnk = b.rnk,
PaymentRnk = p.rnk,
BucketPayment = CASE
WHEN p.Value > b.MaxAmount
THEN b.MaxAmount
ELSE p.Value
END,
CarryOver = p.Value - b.MaxAmount
FROM
BucketsRanked b,
PaymentsRanked p
WHERE b.rnk = 1 AND p.rnk = 1
UNION ALL
SELECT
b.BucketId,
p.PaymentId,
Bucket = b.MaxAmount,
Payment = p.Value,
BucketRnk = b.rnk,
PaymentRnk = p.rnk,
BucketPayment = CASE
WHEN x.PaymentValue > x.BucketValue
THEN x.BucketValue
ELSE x.PaymentValue
END,
CarryOver = x.PaymentValue - x.BucketValue
FROM PaymentsDistributed d
INNER JOIN BucketsRanked b
ON b.rnk = d.BucketRnk + CASE SIGN(CarryOver) WHEN -1 THEN 0 ELSE 1 END
INNER JOIN PaymentsRanked p
ON p.rnk = d.PaymentRnk + CASE SIGN(CarryOver) WHEN +1 THEN 0 ELSE 1 END
CROSS APPLY (
SELECT
CONVERT(
decimal(18,6),
CASE SIGN(CarryOver) WHEN -1 THEN -d.CarryOver ELSE b.MaxAmount END
),
CONVERT(
decimal(18,6),
CASE SIGN(CarryOver) WHEN +1 THEN +d.CarryOver ELSE p.Value END
)
) x (BucketValue, PaymentValue)
)
SELECT
BucketId,
PaymentId,
Bucket,
Payment,
BucketPayment
FROM PaymentsDistributed
;
OPTION (MAXRECURSION n)