题解 | #根据指定记录是否存在输出不同情况#

根据指定记录是否存在输出不同情况

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

拿到题目写了select后面的未完成数和未完成率等,但到‘任意一个0级用户未完成试卷数大于2’这个条件一直不会处理,就参考了webary大佬的题解。发现可以用exists来处理存在性条件,顿时茅塞顿开,因为以前学sql的时候了解过,但使用率太低了导致真需要的时候想不起来。

综合下来本题的关键点有以下几点:

1.因为有些用户没有答题,所以查询所有用户的答题情况的时候,要以user_info为主表! 2.要想到 用exists筛选存在性条件 !! 3.合并两种情况,条件互斥,so只可能有一个结果集:UNION ALL !!!

编写代码分两步:

#1.查询 每个用户 的等级 未完成试卷数 和 未完成率 和 总作答数
#因为有些用户没有答题,所以要查询所有用户的答题情况,要以user_info为主表

select ui.uid uid, level,         **###一定要是ui.uid 才能和level一一对应,er.uid不行**
    count(start_time)-count(submit_time)  incomplete_cnt,
    round(ifnull((count(start_time)-count(submit_time))/count(start_time),0),3)  incomplete_rate,
    COUNT(start_time) as total_cnt    **#为了方便判断第二种情况,我们多构建一个总作答数 **
from exam_record er
right join user_info ui on er.uid=ui.uid
group by uid

最终代码:

/*
用exists筛选存在性条件
合并上述结果,条件互斥,so只可能有一个结果集:UNION ALL
*/

SELECT uid, incomplete_cnt, incomplete_rate
FROM (
    select ui.uid uid, level,     ###一定要是ui.uid 才能和level一一对应
        count(start_time)-count(submit_time)  incomplete_cnt,
        round(ifnull((count(start_time)-count(submit_time))/count(start_time),0),3)  incomplete_rate,
        COUNT(start_time) as total_cnt
    from exam_record er
    right join user_info ui on er.uid=ui.uid
    group by uid
) a
WHERE EXISTS (           #判断为 有任意一个0级用户未完成试卷数大于2
    SELECT uid 
    FROM (
        select ui.uid uid, level,     ###一定要是ui.uid 才能和level一一对应
            count(start_time)-count(submit_time)  incomplete_cnt,
            round(ifnull((count(start_time)-count(submit_time))/count(start_time),0),3)  incomplete_rate,
            COUNT(start_time) as total_cnt
        from exam_record er
        right join user_info ui on er.uid=ui.uid
        group by uid
    ) a
    WHERE `level` = 0 AND incomplete_cnt > 2 )
AND level = 0    #输出0级用户的未完成数和未完成率
union all        ##两种情况用union all 连接
SELECT uid, incomplete_cnt, incomplete_rate
FROM (
    select ui.uid uid, level,     ###一定要是ui.uid 才能和level一一对应
        count(start_time)-count(submit_time)  incomplete_cnt,
        round(ifnull((count(start_time)-count(submit_time))/count(start_time),0),3)  incomplete_rate,
        COUNT(start_time) as total_cnt
    from exam_record er
    right join user_info ui on er.uid=ui.uid
    group by uid
) a
WHERE not EXISTS (       #判断为 没有任意一个0级用户未完成试卷数大于2
    SELECT uid 
    FROM (
        select ui.uid uid, level,     ###一定要是ui.uid 才能和level一一对应
            count(start_time)-count(submit_time)  incomplete_cnt,
            round(ifnull((count(start_time)-count(submit_time))/count(start_time),0),3)  incomplete_rate,
            COUNT(start_time) as total_cnt
        from exam_record er
        right join user_info ui on er.uid=ui.uid
        group by uid
    ) a
    WHERE `level` = 0 AND incomplete_cnt > 2 )
AND total_cnt >0                      #筛选有作答记录的用户 即总作答数大于0即可
order by incomplete_rate asc


也可以用with那个函数创建临时表,不过我没学过那个方法也不习惯用,还是用from后子查询了。

如果还有不用的可以看看webary大佬的解答,真的写的极为清楚,分析逻辑,每个点都有,感谢大佬!

全部评论

相关推荐

11-01 08:48
门头沟学院 C++
伤心的候选人在吵架:佬你不要的,能不能拿户口本证明过户给我。。球球了
点赞 评论 收藏
分享
11-01 20:03
已编辑
门头沟学院 算法工程师
Amazarashi66:这种也是幸存者偏差了,拿不到这个价的才是大多数
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务