题解 | #验证刷题效果,输出题目真实通过率#

验证刷题效果,输出题目真实通过率

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中的比率我们可以直接调用比率的简洁的名字

全部评论

相关推荐

牛客21331815...:像我一投就pass,根本不用焦虑泡池子
点赞 评论 收藏
分享
评论
3
收藏
分享

创作者周榜

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