题解 | #近三个月未完成试卷数为0的用户完成情况#
近三个月未完成试卷数为0的用户完成情况
https://www.nowcoder.com/practice/4a3acb02b34a4ecf9045cefbc05453fa
# 检查每个用户近三个月的作答月份, 再检查这些月份的作答数和完成数是否一致,不一致按完成数输出 WITH temp AS ( SELECT uid, DATE_FORMAT(start_time, "%Y-%m") start_month, submit_time, DENSE_RANK() OVER (PARTITION BY uid ORDER BY DATE_FORMAT(start_time, "%Y%m") DESC) AS month_rank FROM exam_record ) SELECT uid, COUNT(start_month) AS exam_complete_cnt FROM temp WHERE month_rank < 4 GROUP BY uid HAVING COUNT(start_month) = COUNT(submit_time) ORDER BY exam_complete_cnt DESC, uid DESC
根据题意,找到每个人近三个有试卷作答记录的月份中没有试卷是未完成状态的用户的试卷作答完成数,按试卷完成数和用户ID降序排名
目标:找到每个用户,这些用户是满足以下两个条件:1.近三个月(不要求连续)有作答记录 2.这些作答记录是都做完了的
思路:
1.先建立一个临时表,查询出需要的字段:uid,开始时间,提交时间,开始时间的月份排序(年-月)。这一部分用到了date_format()函数和dense_rank()窗口函数,因为同一个月可能有多条记录,能保证都标识出来。 这里我犯了两个错误:把rank作为窗口排序后的列名,但是rank是保留字,所以一直说我语法有错;在临时表里面使用where,窗口函数不能用where。窗口函数通常在SELECT子句中或者作为ORDER BY子句的一部分使用。
2.针对临时表,筛选出排名在前三的,这样就找到了近三个有试卷作答记录的月份,再按用户分组,过滤掉那些未完成作答的记录HAVING COUNT(start_month) = COUNT(submit_time),最后排序。