题解 | #每个6/7级用户活跃情况#

每个6/7级用户活跃情况

http://www.nowcoder.com/practice/a32c7c8590324c96950417c57fa6ecd1

又是一道我觉得很烧脑细胞的题目
有看过我之前写的题解思路的话,其实这道题还是一样,对数据表做简化

题目要求是如下:
很快你就发现,这个要求根本用不上examination_info这个考试信息表,跟您说拜拜勒

那么我们针对其他表一一简化下:

首先是用户表user_info,用户这里是筛选6级和7级这两类,因此用一个where条件即可快速实现
select
    uid
from user_info
where `level` between 6 and 7

其实就是exam_recordpratice_record表啦。要求这里有个雷就是要统计用户总活跃月份数。这里并没有明确说2021年,也意味着2021年以外的记录也要统计进去
因此这里只能做一些小的简化,例如将submit_time拆分成年,月,日期
select
    distinct
        uid,
        Year(submit_time) as e_year,
        Month(submit_time) as e_mon,
        substring_index(submit_time, ' ', 1) as e_day
from exam_record
select
    distinct
        uid,
        Year(submit_time) as e_year,
        Month(submit_time) as e_mon,
        substring_index(submit_time, ' ', 1) as e_day
from practice_record

剩下的就是组装问题啦,那很多人到了这步,是不是很快就想到了用连接(join)的方式去将这三个SQL关联在一起呢。
我一开始也是如此,于是就写了这个SQL语句以便观察怎么实现接下来的统计:
select
    user_info.uid,
    e_year,
    e_mon,
    e_day,
    p_year,
    p_mon,
    p_day
from user_info

left join

(select
    distinct
        uid,
        Year(submit_time) as e_year,
        Month(submit_time) as e_mon,
        substring_index(submit_time, ' ', 1) as e_day
from exam_record) t using(uid)

left join

(select
    distinct
        uid,
        Year(submit_time) as p_year,
        Month(submit_time) as p_mon,
        substring_index(submit_time, ' ', 1) as p_day
from practice_record) t2 using(uid)
where `level` between 6 and 7
可到了后面发现了一个问题:怎么多字段统计总活跃天数呢?怎么多字段统计活跃月份数呢?又怎么去做去重判断呢?
这里我卡壳了,想过直接用count()相加,但无法去重。也想过多字段distinct看是否行得通,也不行
最后我想了下,要不将其拆分开,于是就想到了union这个关键字


union大概作用是将多个查询结果进行合并,因此这道题我觉得必须得用它
因此重写后的SQL语句如下:
select
    distinct
        uid,
        Year(submit_time) as e_year,
        Month(submit_time) as e_mon,
        substring_index(submit_time, ' ', 1) as e_day
from exam_record

union all

select
    distinct
        uid,
        Year(submit_time) as e_year,
        Month(submit_time) as e_mon,
        substring_index(submit_time, ' ', 1) as e_day
from practice_record
这样到了后续也就有了很清晰的思路啦。BUT 我又遇到了新的难题,就是题目还得要求统计2021年试卷作答活跃天数,2021年答题活跃天数。而现在合在一起了,无法直接统计
那有没有办法去解决这个问题呢?答案肯定是有的,其实只要加一个标记区分就可以轻松实现了,即在exam_record内加'exam'这个tag,然后再pratice_record内加上'pra'这个tag即可(tag名字你可以自由DIY)
最后为最终SQL
select
    user_info.uid,
    count(distinct e_year, e_mon) as act_month_total,
    count(distinct if(e_year = 2021, e_day, null)) as act_days_2021,
    count(distinct if(e_year = 2021 and e_tag = 'exam', e_day, null)) as act_days_2021_exam,
    count(distinct if(e_year = 2021 and e_tag = 'pra', e_day, null)) as act_days_2021_question
from user_info

left join

(select
    distinct
        uid,
        'exam' as e_tag,
        Year(submit_time) as e_year,
        Month(submit_time) as e_mon,
        substring_index(submit_time, ' ', 1) as e_day
from exam_record

union all

select
    distinct
        uid,
        'pra' as e_tag,
        Year(submit_time) as e_year,
        Month(submit_time) as e_mon,
        substring_index(submit_time, ' ', 1) as e_day
from practice_record) t using(uid)
where `level` between 6 and 7
group by user_info.uid
order by act_month_total desc, act_days_2021 desc








全部评论
最喜欢大佬写的笔记了,为什么不多写一点 啊啊啊啊啊膜拜
点赞 回复 分享
发布于 2022-08-03 12:21

相关推荐

评论
4
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务