sql - 显示我可以支付的所有分期付款

时间:2013-07-15 08:42:28

标签: sql-server sql-server-2008 tsql

我有一张表,其中包含来自不同客户的许多分期付款。每个客户都有可用的余额。

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

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

2 个答案:

答案 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而不是游标可以获得更好的性能。您可以自由地检查最适合您需求的内容。