如何在几个月前使用 SQL 获得运行平衡的差异?
Posted
技术标签:
【中文标题】如何在几个月前使用 SQL 获得运行平衡的差异?【英文标题】:How to get difference in running balance using SQL by months prior? 【发布时间】:2021-09-11 00:26:14 【问题描述】:我的数据如下所示,是客户在某些月份(2021 年 9 月 12 日凌晨 12:00 仅表示 9 月)的总余额
client_id|balance_month|running_balance
20|September 1,2021,12:00 AM|$1000.00
20|August 1,2021,12:00 AM|$900.00
20|July 1,2021,12:00 AM|$600.00
20|April 1,2021,12:00 AM|$400.00
10|September 1,2021,12:00 AM|-$500.00
10|August 1,2021,12:00 AM|$900.00
10|July 1,2021,12:00 AM|$600.00
10|April 1,2021,12:00 AM|$400.00
我想获取每个客户的最新余额,并查看与上个月、两个月前、三个月前和四个多月前的差异。 (截至本文的 2021 年 9 月)。给定客户端的每个存储桶的总和应等于当前余额。
client_id|0to30|30to60|60to90|90to120|120plus
20 |$100 |$300 |$200 |$0 |$400
10 |$0 |$0 |$0 |$0 |$0
这样,每个客户的分箱总额(100 美元+300 美元+200 美元+0 美元+400 美元)加起来就是当前的未结余额(1000 美元,如果余额为负数,则为 0 美元)。此外,客户可能没有原始数据中显示的上个月(8月)的余额,那么它只是之前一个月的最后一个余额。
如何在 postgresql 中有效地完成此任务?
【问题讨论】:
您的问题说您有“每月汇总”的数据,但样本数据缺少月份。 谢谢我更正了,我知道这可能会产生误导。你的答案是好的,只要首先一个 WITH 语句在数据不存在时将余额前馈到随后的月份。 【参考方案1】:您可以倒数月份并使用条件聚合:
select client_id,
(max(running_balance) filter (where seqnum = 1) -
max(running_balance) filter (where seqnum = 2)
) as month_1,
(max(running_balance) filter (where seqnum = 2) -
max(running_balance) filter (where seqnum = 3)
) as month_2,
(max(running_balance) filter (where seqnum = 3) -
max(running_balance) filter (where seqnum = 4)
) as month_3,
max(running_balance) filter (where seqnum = 4) as month_4
from (select t.*,
row_number() over (partition by client_id order by balance_month desc) as seqnum
from t
) t
group by client_id;
注意:如果您想要明确的月份,则只需使用 filter
中的月份:
select client_id,
(max(running_balance) filter (where balance_month::date = '2021-09-01') -
max(running_balance) filter (where balance_month::date = '2021-08-01')
) as month_1,
(max(running_balance) filter (where balance_month::date = '2021-08-01') -
max(running_balance) filter (where balance_month::date = '2021-07-01')
) as month_2,
(max(running_balance) filter (where balance_month::date = '2021-07-01') -
max(running_balance) filter (where balance_month::date = '2021-06-01')
) as month_3,
max(running_balance) filter (where balance_month::date = '2021-06-01') as month_4
from t
group by client_id;
【讨论】:
这非常好,非常接近。但是在访问 t 之前我需要额外的预处理层。如果原始数据在 9 月份没有任何付款/交易,则可能在 9 月份没有当前余额,与前一个月相同。因此,这需要与每个客户的绝对月份相关,而不仅仅是可用的数据,即如果一个月没有数据,它会将其转发到随后的几个月,包括本月。以上是关于如何在几个月前使用 SQL 获得运行平衡的差异?的主要内容,如果未能解决你的问题,请参考以下文章