我有各种套餐的服务,可以每月,每季度,每半年和每年购买一次。计算各种条件下的经常性支付的未来收入预测
每个软件包都有一个due_on日期,当有人续约时我会增加这个日期。
通过查看本月哪些人有due_on日期,可以轻松计算出本月可以粗略估计的收入。
我遇到麻烦的地方是计算明年我每月可以得到多少收入。我不能以此为基础,因为有些人会在明年支付12次,还有6支等。
这样做的最佳方法是什么? 注意:为此,我忽略了摩擦。 我正在使用PHP和MySQL,但我在寻求理论,所以不应该太重要。
我有各种套餐的服务,可以每月,每季度,每半年和每年购买一次。计算各种条件下的经常性支付的未来收入预测
每个软件包都有一个due_on日期,当有人续约时我会增加这个日期。
通过查看本月哪些人有due_on日期,可以轻松计算出本月可以粗略估计的收入。
我遇到麻烦的地方是计算明年我每月可以得到多少收入。我不能以此为基础,因为有些人会在明年支付12次,还有6支等。
这样做的最佳方法是什么? 注意:为此,我忽略了摩擦。 我正在使用PHP和MySQL,但我在寻求理论,所以不应该太重要。
让我们来计算未来12个月的月收入。
我可以看到两个基本的方法来做到这一点:
每个未来12个月的创建桶的阵列(或哈希)。然后,遍历每个活动订阅,并为每个订阅添加预期的收入,并将其从每个适当的存储桶中添加。例如,如果条款是每月,请将该付款添加到每个存储分区;如果该期限是季度,则将该付款添加到当前的due_date月份存储桶以及之后3个月,6个月和9个月的存储桶;等等。编码相当简单,但有足够的客户生成报告可能需要一些时间。
在有(month
,amount
)列MySQL数据库创建一个临时表,一系列的INSERT语句填充它(有一堆,我会得到他们在一分钟),然后在该表上做一个报告。
这有点不寻常,所以我要详细说明一下。我对你的SQL表格结构做了一些假设,但我试图尽可能使它保持通用。
所以首先你需要临时表,我们将根据当前due_on
日期,每一个月的收入开始往里面:
CREATE TEMPORARY TABLE FutureRevenueReport
SELECT
CONCAT(YEAR(s.due_on), '-', MONTH(s.due_on)) as revenue_month,
s.due_amount as revenue_amount
FROM subscriptions s WHERE s.active = 'True';
现在在同一个MySQL的会议上,执行这一系列插入语句来填补未来的收入:
INSERT INTO FutureRevenueReport(revenue_month, revenue_amount)
SELECT CONCAT(YEAR(s.due_on + INTERVAL 1 MONTH), '-',
MONTH(s.due_on + INTERVAL 1 MONTH)), s.due_amount
FROM subscriptions s WHERE s.active = 'True' AND s.term = 'MONTHLY';
INSERT INTO FutureRevenueReport(revenue_month, revenue_amount)
SELECT CONCAT(YEAR(s.due_on + INTERVAL 2 MONTH), '-',
MONTH(s.due_on + INTERVAL 2 MONTH)), s.due_amount
FROM subscriptions s WHERE s.active = 'True' AND s.term = 'MONTHLY';
INSERT INTO FutureRevenueReport(revenue_month, revenue_amount)
SELECT CONCAT(YEAR(s.due_on + INTERVAL 3 MONTH), '-',
MONTH(s.due_on + INTERVAL 3 MONTH)), s.due_amount
FROM subscriptions s WHERE s.active = 'True' AND s.term = 'MONTHLY';
-- etc, up to + INTERVAL 11 MONTH
-- Now the quarterly:
INSERT INTO FutureRevenueReport(revenue_month, revenue_amount)
SELECT CONCAT(YEAR(s.due_on + INTERVAL 3 MONTH), '-',
MONTH(s.due_on + INTERVAL 3 MONTH)), s.due_amount
FROM subscriptions s WHERE s.active = 'True' AND s.term = 'QUARTERLY';
INSERT INTO FutureRevenueReport(revenue_month, revenue_amount)
SELECT CONCAT(YEAR(s.due_on + INTERVAL 6 MONTH), '-',
MONTH(s.due_on + INTERVAL 6 MONTH)), s.due_amount
FROM subscriptions s WHERE s.active = 'True' AND s.term = 'QUARTERLY';
-- And the same for 9 months
-- Then do the same thing for SEMI-ANNUALLY and + INTERVAL 6 MONTH
-- And now the report:
SELECT revenue_month, sum(revenue_amount) as revenue from FutureRevenueReport
GROUP BY revenue_month;
真棒!谢谢!我想到了第一个,但似乎需要很长时间才能运行。我们实施了第二个,它效果很好!感谢您的深入响应! – 2011-05-06 19:57:45