我有一张表,其中包含来自不同客户的许多分期付款。每个客户都有可用的余额。
我想显示客户可以支付的所有分期付款。
客户1,可用余额400 客户2可用余额500
分期付款表:
Customer ID Instalment amount Available
1 150 400
1 150 400
1 150 400
1 150 400
1 150 400
1 150 400
1 150 400
2 200 500
2 200 500
2 200 500
2 200 500
2 200 500
2 200 500
以下是我想要的结果
Customer ID Instalment amount Available
1 150 400
1 150 400
2 200 500
2 200 500
以下代码无效
DECLARE @DrACAvailable decimal,
@PayAmount decimal,
@RunningTotal decimal
SET @RunningTotal = 0
DECLARE rt_cursor CURSOR
FOR
SELECT T2.PayAmount, T2.DrACAvailable
FROM LoanAutoPayTransactions T2
INNER JOIN LoanAutoPayTransactions T1 on T2.LRAC=T1.LRAC
OPEN rt_cursor
FETCH NEXT FROM rt_cursor INTO @PayAmount, @DrACAvailable
WHILE @@FETCH_STATUS = 0
BEGIN
SET @RunningTotal = @RunningTotal + @PayAmount
IF @RunningTotal >= @DrACAvailable BREAK
UPDATE LoanAutoPayTransactions SET PayAmount=@RunningTotal WHERE StartDate=(SELECT MIN(T2.StartDate) FROM LoanAutoPayTransactions T2 WHERE T2.LRAC=LRAC)
FETCH NEXT FROM rt_cursor INTO @PayAmount, @DrACAvailable
END
CLOSE rt_cursor
DEALLOCATE rt_cursor
答案 0 :(得分:1)
虽然我不完全确定你想要什么,但我试了一下。输出是表变量,但可以很容易地更改为更新查询或其他内容。请试一试,看看它是否能提供您想要的结果:
DECLARE @DrACAvailable decimal,
@PayAmount decimal,
@RunningTotal decimal,
@CustomerID int,
@CurrentCustomerID int
SET @RunningTotal = 0
DECLARE @OutputTable table(
LRAC int,
PayAmount decimal,
DrACAvailable decimal);
DECLARE PaymentCursor CURSOR
FOR
SELECT LRAC, PayAmount, DrACAvailable
FROM LoanAutoPayTransactions ORDER BY LRAC, StartDate
OPEN PaymentCursor
FETCH NEXT FROM PaymentCursor INTO @CustomerID, @PayAmount, @DrACAvailable
WHILE @@FETCH_STATUS = 0
BEGIN
IF @CurrentCustomerID != @CustomerID SET @RunningTotal = 0
SET @CurrentCustomerID = @CustomerID
PRINT 'Processing customer id: ' + CAST(@customerid AS VARCHAR)
SET @RunningTotal = @RunningTotal + @PayAmount
IF @RunningTotal <= @DrACAvailable INSERT @OutputTable (LRAC, PayAmount, DrACAvailable) VALUES (@CustomerID, @PayAmount, @DrACAvailable)
FETCH NEXT FROM PaymentCursor INTO @CustomerID , @PayAmount, @DrACAvailable
END
CLOSE PaymentCursor
DEALLOCATE PaymentCursor
-- Print the output table
SELECT LRAC AS 'Customer ID', PayAmount AS 'Instalment amount', DrACAvailable AS 'Available' FROM @OutputTable
答案 1 :(得分:1)
这是没有游标,任何临时表或表变量表的完整工作示例 - 它可以在视图或用户定义内联函数中使用:
SET NOCOUNT ON
GO
DECLARE @DataSource TABLE
(
[CustomerID] BIGINT
,[InstalmentAmount] SMALLINT
,[Available] SMALLINT
)
INSERT INTO @DataSource ( [CustomerID], [InstalmentAmount], [Available])
VALUES (1, 150, 400)
,(1, 150, 400)
,(1, 150, 400)
,(1, 150, 400)
,(1, 150, 400)
,(1, 150, 400)
,(1, 150, 400)
,(2, 200, 500)
,(2, 200, 500)
,(2, 200, 500)
,(2, 200, 500)
,(2, 200, 500)
,(2, 200, 500)
;WITH RankedDataSource ( [RecordID], [CustomerID], [InstalmentAmount], [Available] ) AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY [CustomerID] ORDER BY [CustomerID] ASC) AS [RecordID]
,[CustomerID]
,[InstalmentAmount]
,[Available]
FROM @DataSource
),
DataSource ( [RecordID], [CustomerID], [InstalmentAmount], [Available], [CurrentAvailable], [Level] ) AS
(
SELECT DISTINCT CAST(0 AS BIGINT)
,[CustomerID]
,[InstalmentAmount]
,[Available]
,[Available]
,0 AS [Level]
FROM RankedDataSource
UNION ALL
SELECT RecursiveMember.[RecordID]
,RecursiveMember.[CustomerID]
,RecursiveMember.[InstalmentAmount]
,RecursiveMember.[Available]
,AnchorMember.[CurrentAvailable] - RecursiveMember.[InstalmentAmount]
,AnchorMember.[Level] + 1
FROM RankedDataSource AS RecursiveMember
INNER JOIN DataSource AS AnchorMember
ON RecursiveMember.[CustomerID] = AnchorMember.CustomerID
AND RecursiveMember.[RecordID] = AnchorMember.[Level] + 1
AND AnchorMember.[CurrentAvailable] - RecursiveMember.[InstalmentAmount] > 0
)
SELECT [CustomerID]
,[InstalmentAmount]
,[Available]
FROM DataSource
WHERE [Level] > 0
ORDER BY [CustomerID]
,[InstalmentAmount]
,[Available]
SET NOCOUNT OFF
GO
重要的部分是Recursive CTE。在大多数情况下,使用CTE而不是游标可以获得更好的性能。您可以自由地检查最适合您需求的内容。