• I found a faster solution (at least on this small dataset).

    ;

    WITH totals AS (

    SELECT *, ABS(Amount) AS Amt, SUM(ABS(Amount)) OVER(PARTITION BY Customer, TransactionType ORDER BY Date ROWS UNBOUNDED PRECEDING ) AS tot

    FROM #t1

    )

    , balances AS (

    SELECT *, MIN(CASE WHEN TransactionType = 'Debit' THEN Date END) OVER(PARTITION BY Customer ORDER BY tot, TransactionType ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS PaidDate,

    LAG(TransactionType) OVER(PARTITION BY Customer ORDER BY tot, TransactionType) AS PrevTransactionType,

    LAG(Date) OVER(PARTITION BY Customer ORDER BY tot, TransactionType) AS PrevDate,

    LAG(tot) OVER(PARTITION BY Customer ORDER BY tot, TransactionType) AS PrevTot

    FROM totals

    )

    SELECT TransactionID, Customer,

    CASE

    WHEN PaidDate IS NOT NULL THEN 0

    WHEN PrevTransactionType = 'Credit' THEN Amt

    ELSE tot - PrevTot

    END AS RemainingBalance,

    CASE

    WHEN PaidDate IS NOT NULL THEN PaidDate

    WHEN PrevTransactionType = 'Debit' THEN PrevDate

    END AS LastRedeemedDate

    FROM balances

    WHERE TransactionType = 'Credit'

    ORDER BY tot, TransactionType

    If I have the time, I'll run a more complete set.

    Drew

    J. Drew Allen
    Business Intelligence Analyst
    Philadelphia, PA