簡體   English   中英

如何使用 PostgreSQL window 函數計算運行余額?

[英]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

dbfiddle 上的演示

遞歸 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM