sql计算逐年累加
还算循序渐进的分享了如何计算累计值
原始数据
1 | INSERT INTO `<yry_fcc_accounts_receivable_doc>` (`status`, `project_number`, `planned_repayment_date`, `total_amount`) VALUES (1, 'XXXX-ls-00035', 1618880400, 55522000.00); |
status | project_number | planned_repayment_date (UTC) | total_amount |
---|---|---|---|
1 | XXXX-ls-00035 | 1618880400 (2021-04-20 09:00:00 ) | 55,522,000.00 |
1 | XXXX-ls-00035 | 1634691600 (2021-10-20 09:00:00 ) | 55,522,000.00 |
1 | XXXX-ls-00035 | 1640048400 (2021-12-21 09:00:00 ) | 9,322,753.19 |
1 | XXXX-ls-00035 | 1650416400 (2022-04-20 09:00:00 ) | 55,522,000.00 |
1 | XXXX-ls-00035 | 1655773200 (2022-06-21 09:00:00 ) | 8,677,689.91 |
1 | XXXX-ls-00035 | 1666227600 (2022-10-20 09:00:00 ) | 36,072,000.00 |
1 | XXXX-ls-00035 | 1671584400 (2022-12-21 09:00:00 ) | 7,992,200.00 |
1 | XXXX-ls-00035 | 1616202000 (2021-03-20 09:00:00 ) | 8,795,298.37 |
1 | XXXX-ls-00035 | 1679360400 (2023-03-21 09:00:00 ) | 6,191,980.41 |
1 | XXXX-ls-00035 | 1681952400 (2023-04-20 09:00:00 ) | 522,000.00 |
1 | XXXX-ls-00035 | 1687309200 (2023-06-21 09:00:00 ) | 6,070,822.59 |
1 | XXXX-ls-00035 | 1695258000 (2023-09-21 09:00:00 ) | 5,991,727.32 |
1 | XXXX-ls-00035 | 1697763600 (2023-10-20 09:00:00 ) | 52,200.00 |
其中status
, project_number
, planned_repayment_date
, total_amount
的含义分别为数据状态、项目编号、应付日期、应付金额。需求为按照年查询该项目每年的应收款项以及截至当年的累计应收款。
先分析这个需求的难点,需求要求返回的结果要包含每年的应收款和累计应收款,其中每年的合计只需要按年分组求和即可,所以关键在于累计合计。
解法1
这种方法我愿称为瞪眼法,其思路是我先看看有多少个年度,再手动写每个年度的累计并union起来,最后与主表的按年分组进行连接即可。
1 | SELECT zb.sk_time |
解法2
这种方法实现思路与上面一直,优化点在于不用再瞪眼写每一年的累计值了,这一需求通过WHERE fb.sk_time <= zb.sk_time
自动计算。
关于简写后的sql,使用到了with子句,这是一些简单描述:
在 SQL 中,
WITH
子句(通常称为 公共表表达式,Common Table Expression,CTE)是一种临时命名的查询结果集,可以在后续的 SQL 语句中被多次引用。
1 | SELECT zb.sk_time |
解法3
针对这个需求,现代一点的做法是使用窗口函数(MySQL8.0后支持),让我们头疼的累计问题一句SUM(SUM(total_amount)) OVER (ORDER BY FROM_UNIXTIME(planned_repayment_date, '%Y')) AS total_amount
搞定。这里因为是按年累计,所以窗口函数中的排序为ORDER BY FROM_UNIXTIME(planned_repayment_date, '%Y')
1 | SELECT |