Let’s say I have a table named transaction with transaction_date, deposit, withdrawal fields. There may or may not be transaction on a day but can have multiple transactions for each day. So, what I need to do is given a date range, say December 1, 2010 to December 31, 2010, I need to figure out the minimum balance on each day. Let’s assume there are transactions before December 1, 2010 as well. Is there anyone who can give me an idea on this one?
Thank you.
Update With Example
tran_date withdraw deposit
2010-11-23 0.00 50.00
2010-12-10 0.00 50.00
2010-12-10 0.00 200.00
2010-12-12 100.00 0.00
2010-12-20 0.00 50.00
2010-12-20 70.00 0.00
2010-12-20 0.00 50.00
2010-12-20 0.00 50.00
2010-12-24 150.00 0.00
In above example, the minimum daily balance from Dec 1 to Dec 10 would be 50. On Dec 10 there are two deposits totaling 70 but the minimum balance on that day would be 50 (carried over from previous day).
Now lets look at multiple transactions.
The carried over on Dec 20 is 200. The first deposit makes it 250, the second one makes it 180, the third one makes it 230 and the last transaction makes it 280. So, the minimum balance for that day would be 180 after withdrawing 70 on the second transaction of the day. Is it possible to generate this using a query on PostgreSQL 8.4 or should I use another approach?
Edit2
This is a full example, including the (minimum) balance from the previous day (as far as I can tell with such a small set of data). It should run on 8.4.
I refactored the derived tables to use CTE (common table expression) to make it (hopefully) a bit more readable:
WITH days AS ( -- generate a liste of possible dates spanning -- the whole interval of the transactions SELECT min(tran_date) + generate_series(0, max(tran_date) - min(tran_date)) AS some_date FROM transaction ), total_balance AS ( -- Calculate the running totals for all transactions SELECT tran_id, days.some_date as tran_date, deposit, withdrawal, sum(deposit - withdrawal) OVER (ORDER BY some_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as balance FROM days LEFT JOIN transaction t ON t.tran_date = days.some_date ), min_balance AS ( -- calculate the minimum balance for each day -- (the smalles balance will have a '1' in the column balance_rank) SELECT tran_id, tran_date, rank() OVER (PARTITION BY tran_date ORDER BY balance) as balance_rank, balance FROM total_balance ) -- Now get everything, including the balance for the previous day SELECT tran_id, tran_date, balance, lag(balance) over (order by tran_date) as previous_balance FROM min_balance WHERE balance_rank = 1;