我有各种套餐的服务,可以按月、按季度、按半年和按年购买。
每个包裹都有一个到期日期,当有人续订时我会增加该日期。
通过查看谁有本月的到期日期,很容易计算出我本月可以大致预期的收入。
我遇到麻烦的地方是计算明年我每个月可以预期的收入。我不能基于due_on,因为有些人明年会支付12次,有些人会支付6次,等等。
做这个的最好方式是什么?注意:为此,我忽略了损耗。我在 PHP 和 MySQL 工作,但我要求的是理论,所以这不应该太重要。
让我们以计算未来 12 个月的月收入为例。
我可以看到两种基本方法:
为接下来的 12 个月中的每个月创建一个存储桶数组(或哈希)。然后,遍历每个活动订阅,并将每个订阅的预期收入添加到每个适当的存储桶中。例如,如果条款是每月,则将该付款添加到每个存储桶中;如果期限是季度,则将该付款添加到当前到期日期月份的存储桶以及之后 3、6 和 9 个月的存储桶;等等。这对代码来说相当简单,但是有足够多的客户生成报告可能需要一些时间。
在您的 mysql 数据库中创建一个包含 ( month
, amount
) 列的临时表,用一系列插入语句填充它(有一堆;我会在一分钟内找到它们),然后对该表进行报告。
这有点不寻常,所以我将更详细地说明它。我正在对您的 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;