[英]How to calculate running balance using PostgreSQL window functions?
我想要一個查詢來跟蹤抵押賬戶的利息。 為簡單起見,假設利息是每年計算的。 還有一次性存款/取款(還款等)。
我想查詢此信息並計算運行余額,大概使用 window 函數。 這是我要查詢的那種表的示例。
year | changes | interest | comment
2020 | 10000 | 2.5 | initial mortgage of 10k
2021 | 0 | 2.0 | next year the rate drops
2022 | 5000 | 2.0 | we borrow an extra 5k
2023 | 0. | 1.5 | rate drop again
我想要一個計算每年運行余額的查詢,如下所示:
year | changes | interest | balance
2020 | 10000 | 2.5 | 10250.0 = 10000 * (1 + 2.5 / 100)
2021 | 0 | 2.0 | 10455.0 = 10250 * (1 + 2.0 / 100)
2022 | 5000 | 2.0 | 15764.1 = (10455 + 5000) * (1 + 2.0 / 100)
2023 | 0. | 1.5 | 16000.56 = 15764.1 * (1 + 1.5 / 100)
如何在 PostgreSQL 中執行此操作?
由於需要將上一年余額乘以當前利息,因此使用遞歸 CTE 最容易實現:
WITH RECURSIVE CTE AS (
SELECT t.year, t.changes, t.interest, t.changes * (1.0 + t.interest / 100.0) AS balance
FROM transactions t
WHERE year = (SELECT MIN(year) FROM transactions)
UNION ALL
SELECT t.year, t.changes, t.interest, (t.changes + CTE.balance) * (1.0 + t.interest / 100.0)
FROM transactions t
JOIN CTE ON t.year = CTE.year + 1
)
SELECT year, changes, interest, ROUND(CAST(balance AS numeric), 2) AS balance
FROM CTE
Output:
year changes interest balance
2020 10000 2.5 10250.00
2021 0 2 10455.00
2022 5000 2 15764.10
2023 0 1.5 16000.56
遞歸 CTE 很可能是更好的方法。 但是可以使用 window 函數來做到這一點。
三個關鍵思想是:
exp(sum(ln()))
作為product()
聚合 function。實際的代碼並不復雜:
select t.*,
(sum(changes * running_interest) over (order by year) /
coalesce(prev_running_interest, 1)
) as val
from (select t.*,
exp(sum(ln(1 + interest / 100)) over (order by year desc)) as running_interest,
exp(sum(ln(1 + interest / 100)) over (order by year desc rows between unbounded preceding and 1 preceding)) as prev_running_interest
from t
) t
order by year;
您會在db<>fiddle中注意到浮點運算引起的輕微誤差。 您始終可以減少小數位數以獲得更具美感的數字。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.