LeetCode-596-超过5名学生的课程
今天带来的是LeetCode for SQL的第三题,主要考察的是group by分组统计和数据去重distinct的用法。
题目
有一个 courses 表 ,有 student (学生) 和 class (课程)。请列出所有超过或等于5名学生的课。例如,表:
代码语言:javascript复制 --------- ------------
| student | class |
--------- ------------
| A | Math |
| B | English |
| C | Math |
| D | Biology |
| E | Math |
| F | Computer |
| G | Math |
| H | Math |
| I | Math |
--------- ------------
最终的结果输出为:
代码语言:javascript复制 ---------
| class |
---------
| Math |
---------
在最下面有个提示:学生在每个课中不应被重复计算。
⚠️这个提示很关键。在给出的数据中是没有学生和课程同时重复的,实际题目中有个坑,看过评论才知道:A同学重修了Math课程
思路
思路1
1、如果只看给出的数据,大部分人估计会写出的脚本如下:
代码语言:javascript复制select
class
from courses
group by class
having count(student) >= 5;
上面的脚本会报错就是没有考虑重修课程的A同学
2、正确的过程是先考虑学生和课程同时分组,取出重修的可能性,这样Math课程便只会出现6次
代码语言:javascript复制select
class
from courses group by class,student
然后在上面临时结果中根据class进行个数统计和having过滤即可,最终脚本为:
代码语言:javascript复制select class
from(select
class
from courses group by class,student) a -- 先根据课程和学生同时分组
group by class
having count(class) >= 5;
思路2
使用having进行分组后的过滤,同时需要会学生去重,这种是个人思路。也是在犯了常规错误之后想到的
代码语言:javascript复制select
class
from courses
group by class
having count(distinct student) >=5; -- distinct去重关键
思路3
思路3和思路1是比较类似的:先去重统计课程和数量,然后筛选出大于或等于5的课程。
1、先去重统计课程和数量。在下面的临时结果就统计出了每个课程出现的次数
代码语言:javascript复制select
class
,count(distinct student)
from courses
group by class;
2、从上面的临时结果中筛选出大于或等于5的即可
代码语言:javascript复制select
class
from(select
class
,count(distinct student) as number -- 去重
from courses
group by class)temp -- 临时结果表
where number >= 5;
思路4
对现有的数据直接先去重得到一个中间结果表,然后对表的数据根据class分组统计找到大于或等于5的课程即可。
1、对现有数据的去重得到中间结果
代码语言:javascript复制select
distinct *
from courses
2、对上面的中间结果分组统计
代码语言:javascript复制select
class
from(
select
distinct *
from courses) t -- 临时表
group by class
having count(class) >= 5;
总结
本题中最大的陷阱就是有重修课程的同学,但是给出的数据中没有展现出来,所以上面的方法中都会出现去重的操作。除了第一种方法:根据课程和学生同时分组统计,本质上也是在去重。