Предполагая, что вы пронумеруете свои транзакции в течение дня, я выбрал следующую схему:
CREATE TABLE transaction (
tran_date date,
num int,
withdraw numeric,
deposit numeric
);
INSERT INTO transaction VALUES
('2010-11-23', 1, 0.00, 50.00),
('2010-12-10', 1, 0.00, 50.00),
('2010-12-10', 2, 0.00, 200.00),
('2010-12-12', 1, 100.00, 0.00),
('2010-12-20', 1, 0.00, 50.00),
('2010-12-20', 2, 70.00, 0.00),
('2010-12-20', 3, 0.00, 50.00),
('2010-12-20', 4, 0.00, 50.00),
('2010-12-24', 1, 150.00, 0.00);
Затем появится следующий запрос, чтобы дать вам ответ:
WITH dates (tran_date) AS (SELECT date '2010-12-01' + generate_series(0, 30)),
transactions AS (SELECT tran_date, num,
coalesce(withdraw, 0) AS withdraw,
coalesce(deposit, 0) AS deposit
FROM dates FULL OUTER JOIN transaction USING (tran_date)),
running_totals AS (SELECT tran_date,
sum(deposit - withdraw) OVER (ORDER BY tran_date, num ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS lagging_total,
sum(deposit - withdraw) OVER (ORDER BY tran_date, num ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS current_total
FROM transactions)
SELECT tran_date, min(least(lagging_total, current_total))
FROM running_totals
GROUP BY tran_date
HAVING tran_date IN (SELECT tran_date FROM dates)
ORDER BY tran_date;
Обратите внимание, однако, что для этого вам нужен PostgreSQL 9.0, потому что предложение 1 PRECEDING
не поддерживается в более ранних версиях. Если вы не можете выполнить обновление, вам, вероятно, понадобится какое-то процедурное решение, как предлагают другие ответы.
В любом случае я рекомендую написать для этого модульные тесты. ; -)