复杂查询基础
这一节从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) |
所以最终的语句是: