Следующее не является коротким и приятным, но используя оператор WITH и CTE , я надеюсь, что логика очевидна.Определены несколько CTE, которые ссылаются друг на друга, чтобы сделать общий запрос более читабельным.В целом цель состояла в том, чтобы просто добавить запись начального сальдо, которая могла бы быть:
/*
DROP TABLE IF EXISTS data;
CREATE temp TABLE data (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
date DATETIME NOT NULL,
amount NUMERIC NOT NULL
);
INSERT INTO data
(date, amount)
VALUES
('2019-09-03', -16.00),
('2019-09-04', 15.00),
('2019-09-04', 15.00),
('2019-09-06', -31.00)
;
*/
WITH
initial_filter AS (
SELECT id, date, amount
FROM data
--WHERE ACCT_NAME = 'Real Solutions'
),
prepared AS (
SELECT *
FROM initial_filter
UNION ALL
SELECT
9223372036854775807 as id, --largest signed integer
(SELECT MAX(date) FROM initial_filter) AS FinalDate,
-(5000.00) --ending balance (negated for summing algorithm)
),
running AS (
SELECT
id,
date,
amount,
SUM(-amount) OVER
(ORDER BY date DESC, id DESC
RANGE UNBOUNDED PRECEDING
EXCLUDE CURRENT ROW) AS balance
FROM prepared
ORDER BY date DESC, id DESC
)
SELECT *
FROM running
WHERE id != 9223372036854775807
ORDER BY date DESC, id DESC;
. Это приводит к следующему
id date amount balance
4 2019-09-06 -31.00 5000
3 2019-09-04 15.00 5031
2 2019-09-04 15.00 5016
1 2019-09-03 -16.00 5001
ОБНОВЛЕНИЕ: первый запрос не выдает правильные сальдо.Строка начального сальдо и оконная функция (т. Е. Предложение OVER) были обновлены для точного суммирования по правильным суммам.
Примечание : сальдо по каждой строке определяется полностью из предыдущих строк, а не изсумма текущей строки, поскольку она работает в обратном направлении от конечного сальдо , а не от предыдущего сальдо строки.