题解 | #每月及截止当月的答题情况#

每月及截止当月的答题情况

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

全部评论

相关推荐

11-27 12:43
已编辑
门头沟学院 C++
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务