SQL Server 数据查询易混点(一)

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进行分组。

猜你喜欢

转载自blog.csdn.net/miha_singh/article/details/80280818