我有各种套餐的服务,可以每月,每季度,每半年和每年购买。
每个包都有一个due_on日期,当有人续订时,我会递增。
通过查看本月谁有到期日,可以很容易地计算出我本月可以大致预期的收入。
我遇到麻烦的地方是计算明年每个月的收入。我不能将它建立在due_on之上,因为有些人将在明年支付12次,有些人将支付6次等等。
最好的方法是什么? 注意:为此我无视磨损。 我在PHP和MySQL工作,但我要求理论,所以这不应该太重要。
答案 0 :(得分:1)
让我们来看看未来12个月的月收入情况。
我可以看到两种基本方法:
为接下来的12个月中的每一个创建一个桶的数组(或哈希)。然后,遍历每个活动订阅,并为每个订阅将该预期收入添加到每个适当的存储桶。例如,如果条款是每月,请将该付款添加到每个存储桶;如果该期限为季度,则将该付款添加到当前due_date月份的桶中,并在此之后的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语句以填补未来的收入:
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;