What I have so far can calculate the most recent date that the running total was negative, however I need the date of when it became negative. Is this possible without splitting it into multiple temp table / CTE queries to maintain performance?
declare @CustomerCode int=2134
select CustomerCode, CustomerType, max(PaymentDate) as MaxPaymentDate
from (
select b.CustomerCode, b.CustomerType, b.PaymentDate from Payments as a
join Payments as b
on a.CustomerCode = b.CustomerCode and a.CustomerType = b.CustomerType
where b.PaymentDate <= a.PaymentDate
AND a.CustomerCode = @CustomerCode
group by b.CustomerCode, b.CustomerType, b.PaymentDate
having sum(b.paymentamount) <= 0
) as T
group by CustomerCode, CustomerType
For example, in the table below I am looking for the row on date 2021-01-07 because the running total of -10 just became negative and it is the most recent time it became negative.
CustomerCode | CustomerType | PaymentDate | PaymentAmount |
---|---|---|---|
123 | retail | 2023-01-01 | 0 |
123 | retail | 2023-01-02 | 10 |
123 | retail | 2023-01-03 | -30 |
123 | retail | 2023-01-04 | 10 |
123 | retail | 2023-01-05 | 20 |
123 | retail | 2023-01-06 | 10 |
123 | retail | 2023-01-07 | -40 |
123 | retail | 2023-01-08 | -10 |
123 | retail | 2023-01-09 | 10 |
2条答案
按热度按时间dgsult0t1#
The initial intent of your query is to compute the running sum of payments for each customer. I would recommend rephrasing your code to use window functions rather than a self-join. This is neater, and much more efficient:
For a given customer, we can just filter the resultset for negative values, order it by date and retain the top row only:
I am not totally sure if you want to use a partition to compute the running sum (your query joins on
CustomerCode
andCustomerType
, but filters onCustomerCode
only). If you wanted the same result for multiple customers, we would use:Update: you want the latest date when each customer's balance became negative (whereas above queries give you the earliest date). We can just tweak the
where
andorder by
clauses for this:ss2ws0br2#
If I understand correctly, you are looking for the most recent time it changed to a negative value :
So using this query we can clearly say that the most recent time it changed to a negative is
2023-01-07
:Result :
o obtain the expected date, we must group successive rows and then select the first date from the most recent group :
Result :
Demo here