计算不同条款下定期付款的未来收入预测

发布于 2024-11-04 19:41:03 字数 274 浏览 1 评论 0原文

我有各种套餐的服务,都可以按月、按季、按年、按年购买。

每个包都有一个 due_on 日期,当有人续订时我会增加该日期。

通过检查本月谁有 due_on 日期,可以轻松计算出本月我大致预期的收入是多少。

我遇到麻烦的地方是计算明年每个月的收入预期。我不能以 due_on 为基础,因为有些人明年会支付 12 次,有些人会支付 6 次,等等。

最好的方法是什么? 注意:为此目的,我忽略了损耗。 我正在使用 PHP 和 MySQL,但我要求的是理论,所以这应该不会太重要。

I have a service with various packages, that can all be purchased monthly, quarterly, semi-annually, and yearly.

Each package has a due_on date which I increment when someone renews.

It's easy to calculate how much revenue I can roughly expect this month, by checking who has a due_on date this month.

Where I'm running into trouble is calculating how much revenue I can expect each month over the next year. I can't base it on due_on, because some people will be paying 12 times in the next year, and some 6, etc.

What is the best way to do this?
Note: for this purpose I am ignoring attrition.
I am working in PHP and MySQL, but I'm asking for theory so that shouldn't matter too much.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

辞别 2024-11-11 19:41:03

让我们以计算未来 12 个月的月收入为例。

我可以看到两种基本方法:

  1. 为接下来的 12 个月中的每个月创建一个存储桶数组(或哈希)。然后,迭代每个活动订阅,并将每个订阅的预期收入添加到每个适当的存储桶中。例如,如果条款是每月,则将该付款添加到每个存储桶中;如果期限是季度,则将该付款添加到当前 due_date 月份的存储桶以及此后 3、6 和 9 个月的存储桶中;等等。编码起来相当简单,但如果有足够多的客户,生成报告可能需要一些时间。

  2. 在 mysql 数据库中创建一个临时表,其中包含 (month, amount) 列,用一系列插入语句填充它(有一堆;我稍后就会找到它们),然后对该表进行报告。

    这有点不寻常,所以我将更详细地说明它。我对您的 SQL 表结构做了一些假设,但我试图使其尽可能通用。

    因此,首先您需要临时表,我们将根据当前 due_on 日期首先用每月收入填充该表:

    创建临时表 FutureRevenueReport
    选择
      CONCAT(YEAR(s.due_on), '-', MONTH(s.due_on)) 作为 Revenue_month,
      s.due_amount 作为收入_amount
    FROM 订阅 s WHERE s.active = 'True';
    

    现在在同一个mysql会话中,执行这一系列插入语句来填充未来的收入:

    INSERT INTO FutureRevenueReport(revenue_month,revenue_amount)
    SELECT CONCAT(YEAR(s.due_on + INTERVAL 1 MONTH), '-', 
                  月份(s.due_on + 间隔 1 个月)), s.due_amount
    FROM 订阅 s WHERE s.active = 'True' AND s.term = 'MONTHLY';
    
    插入 FutureRevenueReport(收入_月,收入_金额)
    SELECT CONCAT(YEAR(s.due_on + INTERVAL 2 MONTH), '-', 
                  月份(s.due_on + INTERVAL 2 MONTH)), s.due_amount
    FROM 订阅 s WHERE s.active = 'True' AND s.term = 'MONTHLY';
    
    插入 FutureRevenueReport(收入_月,收入_金额)
    SELECT CONCAT(YEAR(s.due_on + INTERVAL 3 MONTH), '-', 
                  月份(s.due_on + INTERVAL 3 MONTH)), s.due_amount
    FROM 订阅 s WHERE s.active = 'True' AND s.term = 'MONTHLY';
    -- 等等,最多 + 间隔 11 个月
    
    -- 现在是季刊:
    插入 FutureRevenueReport(收入_月,收入_金额)
    SELECT CONCAT(YEAR(s.due_on + INTERVAL 3 MONTH), '-', 
                  月份(s.due_on + INTERVAL 3 MONTH)), s.due_amount
    FROM 订阅 s WHERE s.active = 'True' AND s.term = 'QUARTERLY';
    
    插入 FutureRevenueReport(收入_月,收入_金额)
    SELECT CONCAT(YEAR(s.due_on + INTERVAL 6 MONTH), '-', 
                  月份(s.due_on + 间隔 6 个月)), s.due_amount
    FROM 订阅 s WHERE s.active = 'True' AND s.term = 'QUARTERLY';
    -- 9个月都一样
    -- 然后对 SEMI-ANNUALLY 和 + INTERVAL 6 MONTH 执行相同的操作
    
    ——现在报告:
    选择 Revenue_month, sum(revenue_amount) 作为来自 FutureRevenueReport 的收入
    按收入_月分组;
    

Let's take the case of figuring out monthly revenue for the next 12 months.

I can see two basic ways to do it:

  1. Create an array (or hash) of buckets for each of the next 12 months. Then, iterate through each active subscription and for each subscription add the expected revenue from that to every appropriate bucket. For example, if the terms are monthly, add that payment to every bucket; if the term is quarterly, add that payment to the current due_date month's bucket and the buckets for 3, 6, and 9 months after that; etc. This is fairly straightforward to code, but with enough customers generating the report could take some time.

  2. Create a temporary table in your mysql database that has columns of (month, amount), fill it with a series of insert statements (there are a bunch; I'll get to them in a minute), and then do a report over that table.

    This is a bit more unusual, so I'm going to spell it out in more detail. I'm making some assumptions about your SQL table structure, but I'm trying to keep it as generic as possible.

    So first you need the temporary table, and we'll fill it initially with per-month revenue based on the current due_on date:

    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';
    

    Now in the same mysql session, execute this series of insert statements to fill in future revenue:

    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;
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文