Home > database >  Calculate conditional running total in SQL
Calculate conditional running total in SQL

Time:07-08

I would like to write an SQL query that calculates the total of outstanding invoices on a daily basis, but couldn't find a solution as to how to do it so far. My table includes an invoice amount, a creation day and a repayment day (which is empty if no repayment has been received yet).

In order to calculate the outstanding invoice amount, I need to get the sum of all amounts that have not been repaid, i.e. the repayment day is empty or after the focal day. Here is an example:

amount creation day repayment day
100 2-7-2022 4-7-2022
100 2-7-2022 3-7-2022
300 3-7-2022
200 4-7-2022
400 5-7-2022 6-7-2022
100 5-7-2022
100 5-7-2022
300 6-7-2022

Now I wish to calculate the outstanding invoice amount at the end of each day. I would like to have a table returned that looks like the following. The amounts that have been repaid are excluded from the daily total.

Date Outstanding invoice
2-7-2022 200
3-7-2022 400
4-7-2022 500
5-7-2022 1100
6-7-2022 1000

Would love to get some input on this.

Thanks!

CodePudding user response:

The first step is to split the two things that can happen in a single record into two separate rows (creation and optional repayment). You do this by "looping" over the table twice, looking at it for creation and then looking at it for repayment:

select
    case payment
        when 1 then repayment_date
        else creation_date
    end date,
    case payment
        when 1 then -amount
        else amount
    end amount
from (select 0 payment union all select 1 payment) payment
join invoice on payment=0 or repayment_date

Then you take the results of that, group by and sum amounts for each date, and use a window sum to get a running total of per date sums:

select
    date_format(date,'%e-%c-%Y') Date,
    sum(sum(amount)) over (order by date) 'Outstanding invoice'
from (
    select
        case
            when payment then repayment_date
            else creation_date
        end date,
        case
            when payment then -amount
            else amount
        end amount
    from (select 0 payment union all select 1 payment) payment
    join invoice on payment=0 or repayment_date
) activity
group by date

fiddle

  • Related