三张表,学生表,课程表,学生_课程表
GROUP BY
- 满足 SELECT子句中的列明必须为分组列或列函数
- 列函数对于group by 子句定义的每个组返回一个结果
这两句话的含义,看具体的例子:
根据student表,student_course表查询所有同学的学号、选课数、总成绩,
首先,我们根据查询的条件得知,需要按照学号进行分组,即
GROUP BY student_id
然后,需要查询的是学号、选课数、总成绩
SELECT student_id,count(course_id),sum(score)
最后,要从student_courese表中查询
FROM student_course
最后我们只要把以上三句拼凑起来,就可以得到我们最终的查询语句:
#查询所有同学的学号、选课数、总成绩 SELECT student_id, count(course_id),
sum(score)
FROM student_course GROUP BY student_id;
再看看上面的两点是如何体现的:
- 列函数对于group by的子句定义的每个组返回一个结果,这里的group by后的条件是student_id,那么最后的结果是按照student_id进行分组的。
- 如果用group by,那么select语句中选出的列要么是group by 中使用到的列,要么就是聚集函数,如sum(), min(), max(), count()等。
注意,以上两点仅对单表有效。
如果是多表联合查询,比如,上面的结果还需要显示stduent表中的student_name:
SELECT sc.student_id,stu.student_name, count(sc.course_id) FROM student_course sc,student stu WHERE sc.student_id = stu.id GROUP BY sc.student_id;
这时,我们发现,select语句中的stu.student_name并不是group by中的条件或者是聚集函数,不过可以知道的是,这个name和group by中的student_id所属的表并不是同一张表,而是另外的student表。
Having
- 通常与group by子句一起使用
- where过滤行,having过滤组
- 出现在同一sql的顺序:where > group by > having
查询平均成绩大于60分的同学的学号和平均成绩
使用上面的分析方法:
按学号分组:
GROUP BY student_id
查询平均成绩和学号:
SELECT student_id,avg(score)
条件是平均成绩大于60,可以分析出这个是针对每个学生的,所以要用having进行分组过滤
HAVING avg(score) > 60
从student_course表查询
FROM student_course
最后,把语句拼接起来:
SELECT student_id, avg(score) FROM student_course GROUP BY student_id HAVING avg(score) > 60