1.group by分组
group by 子句将查询结果按照某一列或多列值分组,分组列值相等的为一组,并对某一组进行统计。
group by子句常用于需要根据某种类型对这种类型的数据进行分类的操作中。例如:根据学号这种类型计算这个学号的学生的总成绩,根据课程,计算这么课程的所有学生的平均分:
--统计每位学生的所有课程的平均分
select sno,avg(score)平均分 from grade
group by grade.sno,sname
--统计课程的平均分
select cno,avg(score) from grade
group by cno
以上是group by子句的简单使用,相信很多人在实际的使用过程中肯定出现过类似的错误:
选择列表中的列 XXX 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中。
这是为什么呢?
group by 中的列必须与选择列表中的列完全匹配,因为group by子句会将表中的元祖按照group by 子句指定的列进行分类,当select中的列没有出现在group by子句中时,对于根据group by中指定的列划分的元组集合中,sql不知道该选取这个集合中的哪个元组的那个未出现在group by 子句而在select 中的列的值,比如:
select sno,avg(score),cno from grade
group by sno
select 中选中的列为sno,avg(score),cno,出现在group by 子句中的是sno,所以sql根据sno对grade表中的元组进行分类,而且score出现在聚合函数中,所以会对sno相等的元组的score进行求平均值运算,而当要选取cno的值时sql犯难了,因为对于sno相等的这些元组,每个元组都可能有不同的cno,这个时候sql就不知道该选取哪个元组的sno值了,于是就报错了。
所以: 对于包含group by 子句的SQL查询语句,选择列表中的列要么出现在group by 子句中,要么出现在聚合函数中。
当查询语句中包含group by 子句而且又涉及多个表时该怎么办呢?
例如,在查询每个学生的平均成绩时,我需要查看这个学生的学号(sno),姓名(sname),平均成绩(avg(score)),分别来自表student,,grade。
try1:
select grade.sno,sname,avg(score) 平均分 from student,grade
group by grade.sno
这个时候会报错:
选择列表中的列 ‘student.sname’ 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中。
错误很显然,sname并没有出现在聚合函数或者group by 子句中。
try2:
select grade.sno,sname,avg(score) 平均分 from student,grade
group by grade.sno,sname
这个虽然不会报错,但是丛结果来看可以很容易发现这根本呢就不是我们想要的结果,从查询语句进行分析我们也可以看出这相当于选中grade的sno和student的sname进行全连接后根据grade.sno和sname进行分组。显然这个结果是错误的.
try3:
select grade.sno,sname ,avg(score)平均分 from grade
inner join student
on student.sno = grade.sno
group by grade.sno,sname
这个语句是正确的。先将grade和student表根据要求连接在根据sno和sname进行分组。