Home > database >  How to get a running total by date while inserting dates for days when no transactions occurred
How to get a running total by date while inserting dates for days when no transactions occurred

Time:05-19

I have a table of transactions that I have successfully queried to get a running total of the amounts per day, partitioned by scenario_id as shown in the following example:

Tables:

Transactions

Transaction Date Scenario_id transaction_amount
5/19/2022 00000000 $.01
5/25/2022 00000000 $5.00
5/18/2022 10000000 $50
5/19/2022 00000000 $.01
5/25/2022 00000000 $5.00
5/18/2022 10000000 $50

Filters

starting_cash start_date end_date
$50,000 5/19/2022 5/25/2022

Code:

SELECT   transaction_date, scenario_id, SUM(transaction_amount) AS net_daily,
                             (SELECT   filters.starting_cash
                                FROM         filters)   SUM(SUM(transaction_amount)) OVER (PARTITION BY scenario_id
ORDER BY transaction_date) AS forecasted_cash
FROM         Transactions
WHERE     transaction_date >=
                             (SELECT   filters.start_date
                                FROM         filters)
GROUP BY transaction_date, scenario_id

Current Result

Transaction Date Scenario_id net_daily Forecasted_cash
5/19/2022 00000000 $.02 $50,000.02
5/25/2022 00000000 $10 $50,010.02
5/18/2022 10000000 $100 $50,100

However, I would like to have all empty dates in the timeline that is filtered for to be populated with $0 net daily while carrying on the forecasted cash running total from the day before:

Desired Result

Transaction Date Scenario_id net_daily Forecasted_cash
5/19/2022 00000000 $.02 $50,000.02
5/20/2022 00000000 $0. $50,000.02
5/21/2022 00000000 $0. $50,000.02
5/22/2022 00000000 $0. $50,000.02
5/23/2022 00000000 $0. $50,000.02
5/24/2022 00000000 $0. $50,000.02
5/25/2022 00000000 $10 $50,010.02
5/18/2022 10000000 $100 $50,100
5/19/2022 10000000 $0 $50,100
5/20/2022 10000000 $0 $50,100
5/21/2022 10000000 $0 $50,100
5/22/2022 10000000 $0 $50,100
5/23/2022 10000000 $0 $50,100
5/24/2022 10000000 $0 $50,100
5/25/2022 10000000 $0 $50,100

What is the best way to accomplish this?

CodePudding user response:

You need to generate a list of dates and then left join to the Transactions table.

CTE filters_dates recursively generates the list of dates. CTE scenario gets the distinct Scenario_id. CTE trans summarize the transactions by date & scenario_id as you have multiple entry with same date. The final result of Forecasted_cash is basically a running total of Transaction _Amount starting_cash

with 
filters_dates as
(
    select starting_cash, start_date, end_date, trans_date = start_date
    from   Filters
    union all
    select starting_cash, start_date, end_date, trans_date = dateadd(day, 1, trans_date)
    from   filters_dates
    where  trans_date < end_date
),
scenario as
(
    select distinct Scenario_id 
    from   Transactions
),
trans as
(
    select trans_date = transaction_date, Scenario_id, trans_amount = sum(transaction_amount)
    from   Transactions
    group by transaction_date, Scenario_id
)
select f.trans_date, 
       s.Scenario_id,
       net_daily = isnull(t.trans_amount, 0),
       Forecasted_cash = f.starting_cash
                         sum(isnull(t.trans_amount, 0)) over (partition by s.Scenario_id
                                                                  order by f.trans_date)
from   filters_dates f
       cross join scenario s
       left join trans t  on  f.trans_date = t.Trans_Date
                          and s.Scenario_id = t.Scenario_id
order by s.Scenario_id, f.trans_date;

CodePudding user response:

It sounds to me like a typical use for a Tally table. This question is similar to yours, make sure to check out the article linked in the accepted answer.

Fill Missing Dates In a Date-Sequenced in SQL using Tally Table

  • Related