续费模式下的客户增长率计算
一家杀毒软件公司的产品采用按时间购买的方式销售,用户必须不断续购“许可 key”才可以继续使用软件,“许可 key”分为半年授权、一年授权和终身授权,详细情况如下:
ID | Key Type | TermOfValidity | Price |
1 | Six months | 6 months | 20 |
2 | One Year | 12 months | 36 |
3 | Unlimited | Infinity | 500 |
下面是该公司推行这种销售模式后前几年的销售记录表:
如果客户授权到期而又没有续购授权,则停止软件使用,不再视为公司客户。请算出公司这几年中每年的客户增长率。
此问题由于涉及到年底结算的问题,而年份又不是确定的,所以需要按天循环,同时用另一个序表来同步记录当前的客户,在每一天的循环中,删去已经过期的用户,添加新的用户,并给老用户续费,而后到了年底再结算用户数量即可。循环结束后,再用结果表即可算出每一年的客户数量增长率。
![]() |
A | B | C | D |
1 | =T("AVwareSales.txt").sort(Date) | >s=date(A1.Date),e=date(A1.m(-1).Date),days=e-s | ||
2 | 1 | elapse@m(?,6) | ||
3 | 2 | elapse@y(?,1) | ||
4 | 3 | 'null | =create(ID,Pattern).record([A2:B4],0).keys(ID) | |
5 | =create(User,ExpDate).keys(User) | =create(Year,UsersNum,GrowthRate) | ||
6 | for 0,days | >d=s+A6 | >A5.delete(A5.pselect@a(ExpDate!=null && ExpDate<d)) | |
7 | for A1.select(date(Date)==d) | =A5.find(B7.User) | =C4.find(B7.KeyID).Pattern | |
8 | if C7==null | >A5.insert(0,B7.User,eval(D7,d)) | ||
9 | else | >C7.run(ExpDate=if(ExpDate, eval(D7,ExpDate))) | ||
10 | if d==e || (day(d)==31 && month(d)==12) | >C5.insert(0,year(d),A5.count()) | ||
11 | =C5.run(if(#>1,GrowthRate=round((UsersNum-UsersNum[-1])/UsersNum[-1],2))) |
https://try.esproc.com/splx?4Uh
A1读出软件销售记录,并按订购日期排序。C1准备一些计算中使用的变量,s为最早的订购日期,e为最晚的订购日期,days为日期差用于循环计算。
A2~B4,根据不同授权的模式,写出每种 key 对应的有效期延长算式,用elapse函数的@m和@y选项来计算6个月或者1年后的结果,如果是终身授权则用null表示。C4将授权信息构成序表:
A5创建记录当前有效用户的序表,C5创建记录年用户数和增长率的结果表。
A6开始,按订单的持续天数循环。在循环体中,B6计算当前订单日期d,C6删除当天已经超过有效期的客户。B7循环当天的所有销售记录,C7查找用户名称,D7查找对应的授权计算模式。如果有效用户表中不存在记录,则生成新的有效用户记录,有效期按照订单日期计算。如果用户已存在,则按照已存在的有效期数据延长。B10判断年底或者循环完成时,C10中将当前的客户数量写入C5的结果表中。
在订单循环过程中,A5会一直记录当前仍在有效期的客户信息:
循环结束后,A11根据C5中每年的客户数量,计算出这几年中每年的客户增长率:
AVwareSales.txt
练习一下…帖子中的写法思路很正,但 B7 格把 A1 全表遍历了 A6 中的 days 次数,执行起来有点慢。因为 A1 已经按照 Date 列排序,所以 B7 中的 select 可以用二分法 select@b(),可以明显提升速度。我也尝试写了一下,从结果来看是对的,但不知道思路有没有问题:
1、数据源初始化一下,按日期排序,再分配一个 ExpDate 到期列;
2、授权使用情况列表,终生有效按 200 年算;
3、数据源按客户编号 User 分组, 计算客户的使用期限,计算时用上一个到期日跟当前续费日期两者大的为基准,因为 Date 列已经事先升序了;
4、数据源按续费日期 Date 列中的年份分组,当前留存客户以小于等于当前年份的为基础再筛选出 ExpDate 大于等于当前年份最后一天的记录计算不重复客户数;
5、计算增长率
有个不好的地方是,在筛选当前留存客户集合的时候,~[:0] 这部分表示从一开始到当前,这个集合会越来越大,在这个基础上再 select,遍历量也不小。
如果大佬们有闲情,可不可以指导一下,有没有其它写法,谢谢🙏
=T("AVwareSales.txt").run(Date=date(Date)).sort(Date).derive(:ExpDate) =["elapse@m(?,6)","elapse@y(?,1)","elapse@y(?,200)"] =A1.group(User).run(~.run(ExpDate=eval(A2(KeyID),max(ExpDate[-1],Date)))) =A1.group(year(Date):Year;(r=~[:0]).conj(~.select(ExpDate>=pdate@ye(r.m(-1).Date))).icount(User):UsersNum) =A4.derive(if(p=UsersNum[-1],round(UsersNum/p-1,2)):GrowthRate)
英文版