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

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

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

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

题目主要信息:

  • 统计每个6/7级用户总活跃月份数、2021年活跃天数、2021年试卷作答活跃天数、2021年答题活跃天数,按照总活跃月份数、2021年活跃天数降序排序
  • 用户信息表user_info(uid用户ID,nick_name昵称, achievement成就值, level等级, job职业方向, register_time注册时间)
  • 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分)
  • 题目练习记录表practice_record(uid用户ID, question_id题目ID, submit_time提交时间, score得分)

问题拆分:

  • 试卷以开始答题时间作为活跃时间,只要用户答题了就代表活跃,不管有没有完成。先筛选出用户ID,开始答题时间作为活跃时间,开始答题的月份作为活跃月份,开始答题的日期作为活跃天,标记tag为'exam'。select uid, start_time as act_time, date_format(start_time, '%Y%m') as act_month, date_format(start_time, '%Y%m%d') as act_day, 'exam' as tag
  • 题目以提交时间作为活跃时间,因为表格中没有开始时间。先筛选出用户ID,提交时间作为活跃时间,提交的月份作为活跃月份,提交的日期作为活跃天,标记tag为'question'。select uid, submit_time as act_time, date_format(submit_time, '%Y%m') as act_month, date_format(submit_time, '%Y%m%d') as act_day, 'question' as tag
  • 将上述两个筛选结果合并作为新表exam_and_practice。知识点:union all
  • 活跃信息在新表exam_and_practice中,用户等级信息在user_info中,因此在表user_info右边连接新表,以uid为准。知识点:left join...on... 使用left join是因为要使没有活跃的用户在连接后的表中显示活跃信息为空而不是消失。
  • 从连接后的表中筛选出等级大于等于6的用户,然后统计每个用户的活跃信息:
    • 每个用户都要统计,因此要对uid分组。知识点:group by
    • 统计每个uid下在连接后的表中的不同的活跃月份数。count(distinct act_month) as act_month_total 知识点:distinct、count()
    • 统计每个uid下在连接后的表中不同的活跃天数,前提是活跃时间的年份等于2021. count(distinct case when year(act_time) = 2021 then act_day end) as act_days_2021 知识点:case when...then...end
    • 统计每个id在连接后表中活跃时间的年份等于2021且标签为'exam'的不同活跃天数。count(distinct case when year(act_time) = 2021 and tag = 'exam' then act_day end) as act_days_2021_exam 知识点:case when...and...then...end
    • 统计每个id在连接后表中活跃时间的年份等于2021且标签为'question'的不同活跃天数。count(distinct case when year(act_time) = 2021 and tag = 'question' then act_day end) as act_days_2021_question 知识点:case when...and...then...end
  • 对选择的信息按照总活跃月份数、2021年活跃天数降序排序输出。order by act_month_total desc, act_days_2021 desc 知识点:order by

代码:

select u_i.uid as uid,
       count(distinct act_month) as act_month_total,
       count(distinct case 
             when year(act_time) = 2021 
             then act_day 
             end) as act_days_2021,
       count(distinct case 
             when year(act_time) = 2021 
             and tag = 'exam' 
             then act_day 
             end) as act_days_2021_exam,
        count(distinct case
             when year(act_time) = 2021
             and tag = 'question'
             then act_day
             end) as act_days_2021_question
from user_info u_i
left join (select uid,
             start_time as act_time,
             date_format(start_time, '%Y%m') as act_month,
             date_format(start_time, '%Y%m%d') as act_day,
             'exam' as tag
      from exam_record
      union all 
      select uid,
             submit_time as act_time,
             date_format(submit_time, '%Y%m') as act_month,
             date_format(submit_time, '%Y%m%d') as act_day,
             'question' as tag
      from  practice_record
      ) exam_and_practice
on exam_and_practice.uid = u_i.uid
where u_i.level >= 6
group by uid
order by act_month_total desc, act_days_2021 desc

孤帆远影碧空尽 文章被收录于专栏

牛客网各类题单题解~

全部评论
厉害 其他的都想到了 就是没想到在两个表连接的时候都标上标签 导致自己绕来绕去的
12 回复 分享
发布于 2022-03-02 10:38
结构化思维,这是我在新手阶段最需要的答案和解法了,感谢
2 回复 分享
发布于 2022-03-31 11:34
写的sql 还是比较简洁
2 回复 分享
发布于 2021-11-12 11:24
解题思路很像日常处理excel数据,先拉大表数据,再从中筛选想要的数据的思路,有一定的启发。
1 回复 分享
发布于 2023-04-24 00:19 广东
见过最好最全最清晰的题解!感谢!
1 回复 分享
发布于 2022-09-30 18:20 北京
我连答案都看不明白
点赞 回复 分享
发布于 2024-05-17 15:35 台湾
感谢
点赞 回复 分享
发布于 2023-09-26 19:39 广东
请问各位大佬,uid1003的数据没有记录,不应该都是Null吗,看代码没有转化成0的命令呀,请问是怎么做到显示为0的呢
点赞 回复 分享
发布于 2023-04-29 21:04 江苏
感谢大佬,我总算知道如何简化SQL代码了;在知道`case when end`之前,我都是将每一字段逐一求出,再连接起来的,有了`case when end` 我不需要写多层嵌套的SQL了
点赞 回复 分享
发布于 2023-04-19 16:17 广东
太牛了!!!
点赞 回复 分享
发布于 2023-03-30 13:05 重庆
如果practice和exam是同一天,那是不是活跃天数只算一天,这样是不是需要去重?
点赞 回复 分享
发布于 2023-03-21 23:35 台湾
请问一下大佬们,这个地方不在where里面筛选2021年的信息转而采用case when来筛选是不是因为用where会把某些6,7级的用户给移除出表
点赞 回复 分享
发布于 2023-02-24 11:22 湖北
强,很有帮助,感谢!
点赞 回复 分享
发布于 2023-01-03 15:42 法国
tag=exam 是啥意思,为啥要打标签
点赞 回复 分享
发布于 2022-11-24 07:56 广东
哪里写“试卷以开始答题时间作为活跃时间,只要用户答题了就代表活跃,不管有没有完成”了
点赞 回复 分享
发布于 2022-10-17 23:51 江苏
朴素有效,膜拜
点赞 回复 分享
发布于 2022-09-21 12:17 北京
你们一道题平均刷题时常是多少哇,我有时候一道题不看答案做半天正常么
点赞 回复 分享
发布于 2022-07-28 18:49
思路清晰 代码优美 感谢大佬
点赞 回复 分享
发布于 2022-07-12 12:05
牛批
点赞 回复 分享
发布于 2022-06-17 18:18
好厉害
点赞 回复 分享
发布于 2022-05-23 16:09

相关推荐

评论
278
45
分享

创作者周榜

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