如何跟踪帐户的最小和最大余额

How to Track Min and Max Balance of an Account

我正在查看跟踪银行账户的最大和最小余额。有两个table:

AccountBalanceHistoryTable - 这记录了每个帐户在每个月底的余额

TransactionTable - 这记录了帐户上发生的所有交易

我创建了以下查询以将这两个 table 放在一起以获得 运行 余额,然后我将使用它来 select 最大和最小余额:

select
    i.acct_id,
    i.trnxamt,
    i.date_trnx,
    EXTRACT (MONTH from i.date_trnx) month_num,
    EXTRACT (YEAR from i.date_trnx) as year_num,
    (
        j.balance + sum(i.trnxamt) over (partition by i.acct_id order by i.date_trnx ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
    ) as balance_calc
from
    TransactionTable i
    left join (
        select
            acct_id,
            monthend_date,
            balance,
            row_number() over (partition by acct_id order by monthend_date) as rn
        from
            AccountBalanceHistoryTable
    ) j on i.acct_id = j.acct_id
    and j.rn = 1

我使用 AccountBalanceHistoryTable 获取我看到的一个月记录的最后余额(第一行),并将其作为下个月的起始余额。

假设 AccountBalanceHistoryTable 显示帐户 123456 在 8 月 31 日的余额为 100 美元。以下仅显示一些示例交易以及 Balance_Calc 将计算的内容:

Acct_ID TrnxAmnt Date_Trnx Month_num Year_num Balance_Calc
123456 -55 29-Sep-20 9 2020 45
123456 10 30-Sep-20 9 2020 55
123456 100 1-Oct-20 10 2020 155
123456 20 1-Oct-20 10 2020 175

我遇到的问题是,上面说的是 10 月 1 日。在该帐户 10 月份发生任何交易之前,期初余额为 55 美元(9 月 30 日的期末余额)。这 55 美元实际上应该是我 10 月份的最低余额,但如果我采用上面的 table 和 select 2020 年 10 月的最低和最高余额,它将给我 155 美元的最低余额和最高余额175 美元,因为这些是上述子查询结果中显示的仅有的两条记录。

诀窍是 转移 月末 平衡从午夜到下个月的 1 号。

这里是余额table

的例子
select * from AccountBalanceHistory
where acct_id = 123456 
order by monthend_date;

   ACCT_ID MONTHEND_DATE          BALANCE
---------- ------------------- ----------
    123456 31.08.2020 00:00:00        100
    123456 30.09.2020 00:00:00         55
    123456 31.10.2020 00:00:00        175

和您的交易 table

select * from Transaction
where acct_id = 123456 
order by date_trnx;

   ACCT_ID DATE_TRNX              TRNXAMT
---------- ------------------- ----------
    123456 29.09.2020 00:00:00        -55
    123456 30.09.2020 00:00:00         10
    123456 01.10.2020 00:00:00        100
    123456 01.10.2020 00:00:00         20

查询 unions 两个来源并计算 trasnaction month,这是 1st 的余额下个月.

请注意,每一行都有它的来源 BAL 或 TX - 这将用于 正确排序

with tx as (
select 'BAL' source, acct_id,  monthend_date  date_trnx, trunc(monthend_date+1,'MM') tx_month, balance, 0 trnxamt from AccountBalanceHistory
union all
select 'TX', acct_id, date_trnx,trunc(date_trnx,'MM') tx_month, trnxamt balance, trnxamt from Transaction
)
select *
from tx
where acct_id = 123456 
order by date_trnx;

SOU    ACCT_ID DATE_TRNX           TX_MONTH               BALANCE    TRNXAMT
--- ---------- ------------------- ------------------- ---------- ----------
BAL     123456 31.08.2020 00:00:00 01.09.2020 00:00:00        100          0
TX      123456 29.09.2020 00:00:00 01.09.2020 00:00:00        -55        -55
TX      123456 30.09.2020 00:00:00 01.09.2020 00:00:00         10         10
BAL     123456 30.09.2020 00:00:00 01.10.2020 00:00:00         55          0
TX      123456 01.10.2020 00:00:00 01.10.2020 00:00:00         20         20
TX      123456 01.10.2020 00:00:00 01.10.2020 00:00:00        100        100
BAL     123456 31.10.2020 00:00:00 01.11.2020 00:00:00        175          0

balance 包含余额或交易金额,在我们添加之前它不是很有趣 对每个月使用分析窗口函数(从月初到当前行)

with tx as (
select 'BAL' source, acct_id,  monthend_date  date_trnx, trunc(monthend_date+1,'MM') tx_month, balance, 0 trnxamt from AccountBalanceHistory
union all
select 'TX', acct_id, date_trnx,trunc(date_trnx,'MM') tx_month, trnxamt balance, trnxamt from Transaction
)
select 
SOURCE, ACCT_ID, DATE_TRNX, TX_MONTH,  
sum(BALANCE) over (partition by ACCT_ID,TX_MONTH order by date_trnx, decode (SOURCE,'BAL',1,'TX',2), trnxamt desc) as BALANCE,
TRNXAMT
from tx
where acct_id = 123456 
order by date_trnx;

SOU    ACCT_ID DATE_TRNX           TX_MONTH               BALANCE    TRNXAMT
--- ---------- ------------------- ------------------- ---------- ----------
BAL     123456 31.08.2020 00:00:00 01.09.2020 00:00:00        100          0
TX      123456 29.09.2020 00:00:00 01.09.2020 00:00:00         45        -55
TX      123456 30.09.2020 00:00:00 01.09.2020 00:00:00         55         10
BAL     123456 30.09.2020 00:00:00 01.10.2020 00:00:00         55          0
TX      123456 01.10.2020 00:00:00 01.10.2020 00:00:00        155        100
TX      123456 01.10.2020 00:00:00 01.10.2020 00:00:00        175         20
BAL     123456 31.10.2020 00:00:00 01.11.2020 00:00:00        175          0

现在一切就绪,可以按帐户和月份

进行简单的 MINMAX 聚合分组
with tx as (
select 'BAL' source, acct_id,  monthend_date  date_trnx, trunc(monthend_date+1,'MM') tx_month, balance, 0 trnxamt from AccountBalanceHistory
union all
select 'TX', acct_id, date_trnx,trunc(date_trnx,'MM') tx_month, trnxamt balance, trnxamt from Transaction
), tx2 as (
select 
SOURCE, ACCT_ID, DATE_TRNX, TX_MONTH,  
sum(BALANCE) over (partition by ACCT_ID,TX_MONTH order by date_trnx, decode (SOURCE,'BAL',1,'TX',2), trnxamt desc) as BALANCE,
TRNXAMT
from tx
where acct_id = 123456)
select acct_id, TX_MONTH, min(BALANCE), max(BALANCE) 
from tx2
group by acct_id, TX_MONTH
order by 1,2;

   ACCT_ID TX_MONTH            MIN(BALANCE) MAX(BALANCE)
---------- ------------------- ------------ ------------
    123456 01.09.2020 00:00:00           45          100
    123456 01.10.2020 00:00:00           55          175
    123456 01.11.2020 00:00:00          175          175