题解 | #统计作答次数#
统计作答次数
https://www.nowcoder.com/practice/45a87639110841b6950ef6a12d20175f
描述
有一个试卷作答记录表exam_record,请从中统计出总作答次数total_pv、试卷已完成作答数complete_pv、已完成的试卷数complete_exam_cnt
重点
主要在于已完成的试卷数的统计,因为这个带有条件,且需要统计聚合结果,很自然可以想到 使用 聚合函数与case when 结合。
答案1
select count(*) as total_pv, count(score) as complete_pv, count(distinct case when score is null then null else exam_id end) as complete_exam_cnt from exam_record
答案2
select count(*) as total_pv, count(score) as complete_pv, count(distinct exam_id,score IS NOT NULL or null) as complete_exam_cnt from exam_record
牛客网首赞的错误案例
select count(*) as total_pv, count(score) as complete_pv, count(distinct exam_id AND score IS NOT NULL) as complete_exam_cnt from exam_record
该答案错误在,无论有几个通过课程都会返回2.
首先可以明确,count中是可以加条件的,但是我们得了解他的运行内核。
第一步判断
- 比如这里的score is not null 是判断,符合条件的返回 true ,即为1
- 不符合的返回 false ,即为0 .
第二步判断
- exam_id and 与上一步的结果进行逻辑运算
- exam_id 本身为值,可以理解为真 在 and 逻辑下,上一步的1,0并不会变化
第三步
- 经过and运算之后,count中只剩下一列数据,多行1和0
- distinct 去重后,就只剩下两行数据 1 和 0
得出结果,恒为2
所以count 中出现条件,就是进入逻辑运算,要明白他的执行逻辑,才可以.
正确答案的执行逻辑
- 第一步
- 判断score是否为null 如果是即为真 返回1 如果不是返回 null
- 注意这里如果不加 or null 不是null的时候只会返回false 0
- 第二步
- 从之前的逻辑判断,变为多列组合
- 第三步
- 去重得到结果
- 第四步
- 使用count对 distinct 求行数
- count 本身是不可以对多列求行数的,distinct 的加入是的多列成为一个整体,可以求出现的行数了
- 这里本来有五行,由于有列包含 null,count distinct在计算时只返回非null的行,所以实际只计算了三行的数据
count加条件常用句式 count( 列判断 or null)