题解 | #试卷完成数同比2020年的增长率及排名变化#
试卷完成数同比2020年的增长率及排名变化
http://www.nowcoder.com/practice/13415dff75784a57bedb6d195262be7b
问题的关键在于最后一个字段排序的变化问题。题目字段默认的是digint(整数类型)为unsigned 类型。
如果直接用21的排名-20的排名,就会出现一个错误是:digint unsigned value is out of range in(exam_cnt_rank_21-exam_cnt_rank_20... )之类的。大概意思就是数据默认定义的digint类型是unsigned,unsigned和signed的区别在于unsigned是非负数,也就是默认只能为正数和0,本题中会出现21年排名-20年排名为负数的情况,所以需要使用if函数,这样的方法来修正可能会出现负数的情况
if(exam_cnt_rank_21>=exam_cnt_rank_20,exam_cnt_rank_21-exam_cnt_rank_20,(-(exam_cnt_rank_20-exam_cnt_rank_21))) exam_delta
内心OS(其实mysql这一些列的题目都很好,但是在进阶的部分我作为菜鸟新手,不明白为什么题目的描述会那么容易让人产生歧义,并且给到的范例数据和答案往往都不说清楚埋藏的陷阱,非要让你自己去瞎猜,例如本题三个雷
第一个就是最后的这个unsigned,实在是不明白最后这里放个这个目的是啥???
第二个是给到的表格数据里面每个用户id在每一天做的试卷id都不同,不是简单的根据试卷id分组求和就完了,相当于题目默认是同一个用户同一天可能会做好几次同一份试卷,但是计算数值时只能计算一次???(这个因为之前被坑的太多次所以这个没被坑到)
第三个是给的事例答案最后一个字段排名的变化是正值,“排名1=>2,后退1名。”这都是啥?然后给到的答案表格里确是正1,实际最后做题的时候非要给你搞一个负值的情况???)
不知道有多少刷题刷到这里的朋友跟我有一样的感悟... 还有一些大神也会在解答区分享自己的代码和思想,觉得他们思维逻辑真的很厉害,如果对书写规范更精进一些的话就更完美了。
本人也是小白看视频刷题,都是自己摸索,书写规范也是查了一些资料然后根据自己的理解写的,希望大家读起来能更容易更简单一些。其他部分的代码其实都很简单,我写的也不够简练,大家应该也不用参考。以上。
SELECT tag, exam_cnt_20, exam_cnt_21,
CONCAT(ROUND((exam_cnt_21-exam_cnt_20)*100/exam_cnt_20,1),'%') growth_rate,
exam_cnt_rank_20, exam_cnt_rank_21,
IF(exam_cnt_rank_21>=exam_cnt_rank_20,
exam_cnt_rank_21-exam_cnt_rank_20,
(-(exam_cnt_rank_20-exam_cnt_rank_21))
) rank_delta
FROM
(SELECT exam_id, SUM(c1) exam_cnt_20,
RANK() OVER(ORDER BY SUM(c1) DESC) exam_cnt_rank_20 from
(SELECT exam_id, uid,
COUNT(DISTINCT CASE WHEN date_format(submit_time,'%y%m%d')
BETWEEN '200101' AND '200630'
THEN date_format(submit_time,'%y%m%d')
END) c1
FROM exam_record
GROUP BY exam_id, uid
) r1
GROUP BY exam_id
HAVING exam_cnt_20<>0
) r2
JOIN
(SELECT exam_id, SUM(c1) exam_cnt_21,
RANK() OVER(ORDER BY SUM(c1) DESC) exam_cnt_rank_21
FROM
(SELECT exam_id, uid,
COUNT(DISTINCT CASE WHEN date_format(submit_time,'%y%m%d')
BETWEEN '210101' AND '210630'
THEN date_format(submit_time,'%y%m%d')
END) c1
FROM exam_record
GROUP BY exam_id, uid
) r1
GROUP BY exam_id
HAVING exam_cnt_21<>0
) r3
ON r2.exam_id=r3.exam_id
JOIN examination_info ei ON r2.exam_id=ei.exam_id
ORDER BY growth_rate DESC, rank_delta DESC