题解 | #验证刷题效果,输出题目真实通过率#
验证刷题效果,输出题目真实通过率
https://www.nowcoder.com/practice/c4fd4b545a704877b510f18503ad523f
select user_id, count(distinct if(result_info=1,question_id,null))/count(distinct question_id) as question_pass_rate, sum(result_info)/ count(1) as pass_rate, count(1)/count(distinct question_id) as question_per_cnt from done_questions_record group by user_id having question_pass_rate > 0.6 order by user_id asc ;
一、一开始会被绕晕,但是总得来说,首先大方针是group by 用户,即三个率都是对于每一个用户来计算的
二、
1】第一个比率,比较难,“不同题目”翻译为“每个用户他做的所有题目”,即分母容易确定,为总的题目数(题目我可以反复做,但是总题目数一定是一个distinct的值),即 count(distinct question_id)
分子是此题难点,举个例子我做了20次题目(提交),其中我提交反馈做对了15次(提交且通过),这15次当中实际上只出现了10道题(提交且通过的题目取distinct),在对于每一个user的groupby的范围内,我们知道每一行一定是默认满足了(提交)的条件,即如果我问你每一个人做了多少次题,在groupby范围内,我可以直接用count(1)来计算,有多少行就一定代表我提交了多少次, 即20次题目可以用count(1)快速计算,15次做对的呢?count(增加result_info=1筛选),而result_info有01性质,我们直接用sum(result_info)表示出做对的次数;这时候如何表示那10道题呢?即count(筛选1:result_info = 1,且 筛选2:去重question_id),如何表示这个过程呢?想一想它实际上就是一个case when的衍生列形式的计算,而一些具有case when性能的条件转换函数就非常的nice了,mysql中最常用的莫过于if,这时候,我们用if 来筛选,if(result_info = 1, question_id , null ) 这一步实际上筛选出了那20道中的 (15次题,5道为null),mysql中的distinct又有一个重要属性,那就是它去去重一列值后不会输出null的结果,即 distinct(15次题,5道为null)就等于distinct(15次题),那么就等于10道不同的题
2】第二个比率,就简单了
3】第三个比例,也简单了
三、最后having过滤groupby每个区间的数据,注意在mysql中,having虽然发生于select之前,但是仍然可以使用别名,即having中的比率我们可以直接调用比率的简洁的名字
海康威视公司福利 1125人发布