3

我有一张桌子,上面有来自不同客户的许多分期付款。每个客户都有可用余额。

我想显示客户可以支付的所有分期付款。

客户 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
4

2 回答 2

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
于 2013-07-15T09:52:57.747 回答
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

重要的部分是递归 CTE。在大多数情况下,在游标上使用 CTE 会带来更好的性能。您可以自由检查最适合您需求的内容。

于 2013-07-15T10:42:50.390 回答