复杂查询基础
这一节从group by和having两个关键语法入手,学习一下写sql的基本思路。
数据库准备:
1 | -- ---------------------------- |
第一个问题
查询所有同学的学号、选课数、总成绩
针对sql问题,不需要一口气全部写出来,我们先分解逐个击破,最后再合体。
分析题目,他要查询的是每个学生的学号,选课数,总成绩
那么先把关键字列出来:
1 | #首先是要查询,肯定有select关键字 |
我们看到,有一些函数在里面,比如count和sum,那么我们会想到一般情况下是与group by结合使用的。
因为是查询每个学生,那么必然是根据每个学生的id进行分组了。
1 | group by student_id |
此时,因为涉及的student_id,course_id以及score只需要一张score表就可以解决,那么拼接起来就是:

我们进行explain分析一下:
1 | explain SELECT student_id,count(course_id),sum(score) |
显示:

基本的原理就是:首先根据group by进行分组,分组出来的数据缓存到一张临时表中,然后再做count之类的计算显示。
并且,本题是针对一张表,所以有一个规则是:如果用group by,那么你的select语句中选出的列要么是group by里用到的列,要么就是sum min等列函数的列。所以这里group by和后面是student_id,所以select后面可以查询student_id,但是不能查询course_id等字段。
第二个问题
查询所有同学的学号、姓名、选课数、总成绩
注意观察,其实就是比上一个问题多一个字段name,但是区别比较大,因为一张score表已经不够用了。这个时候还需要student表了,即两张表联合查询。那么只要搞一个连接条件即可:

第三个问题
查询平均成绩大于60分的同学的学号和平均成绩
我们再来分解看看:
1 | #查询肯定用到select |
最后,有一个条件是:平均成绩大于60分,此时就需要对查询出来的分组进行过滤筛选了,此时having闪亮登场。

测试了一下,下面两条sql都是一样的效果:
1 | select * from course where course_id = 1 |
第四个问题
查询没有学全所有课的同学的学号、姓名
这个稍微复杂一点点,我们还是分解来看看:
1 | #查询肯定用到select |
因为需要查询课程没有学满的学生,所以需要先查询所有课程的数量:
1 | select count(1) from course |
此时,我们需要利用这个查询语句作为结果再进行查询,即子查询。对于上面的分组要进行筛选
1 | having count(sc.course_id) < (select count(1) from course) |
所以最终的语句是:
