题解 | #每月及截止当月的答题情况#
每月及截止当月的答题情况
https://www.nowcoder.com/practice/1ce93d5cec5c4243930fc5e8efaaca1e
这个题我觉得是有点难的,写多了Hql再转这个确实会容易陷入开窗如何distinct的问题,hql有办法好处理,但是mysql好像不能那样干,我就在这上面墨迹了很久。最后找资料发现有人遇到了类似的问题,采用的rk,然后就恍然大悟。
标记方向从里到外(一个select为一层),从小到大,描述如下
step1:1层主要使用了row_number 通过uid做分区获取到了用户记录的出现顺序,目的是为了第二层计算accMau(累计到当前日期的用户数量),这里order by我用得是start_month,当然你可以用具体日期order by
step2: 2层计算accMau(累计到当前日期的用户数量),按照start_month 进行order by,只计算rk=1的,rk=1说明这个用户记录是这个用户最早出现的记录,rk=2,=3的都是后面才出现的,不用来统计人数。
step3: 第三层,group by得到每个月的mau,同时可以得到cum_sum_uv,直接取分组的max即可。
setp3: 第四层,主要是通过cum_sum_uv 计算用户的month_add_uv,每个记录的cum_sum_uv 减去上一条month_add_uv则是新增的用户,第一条数据前面没有记录,所有用iffNull控制一下。
step4:第五层,就算max_month_add_uv,因为第五层用到了month_add_uv,所以开了第五层。计算直到目前为止,最大的新增数量
select e.start_month, e.mau,e.month_add_uv, max(e.month_add_uv) over(order by e.start_month) as max_month_add_uv, e.cum_sum_uv from ( select d.start_month, d.mau, IFNULL(d.cum_sum_uv - lag(d.cum_sum_uv) over(order by d.start_month),d.cum_sum_uv) as month_add_uv, d.cum_sum_uv from ( select c.start_month,count(distinct uid) as mau, max(accMau) as cum_sum_uv from ( select b.start_month,b.uid, sum(rk=1) over(order by start_month) as accMau from ( select date_format(a.start_time,'%Y%m') as start_month,row_number() over(partition by a.uid order by date_format(a.start_time,'%Y%m')) as rk,a.uid from exam_record a ) b ) c group by c.start_month ) d ) e