拖了一个星期,终于开始写第三篇了。走起!
聚合函数:
SQL中提供的聚合函数可以用来统计、求和、求最值等等。
分类:

(计数规范) 表名
其中,计数规范包括:
- * :计数所有选择的行,包括NULL值;
- ALL 列名:计数指定列的所有非空值行,如果不写,默认为ALL;
- DISTINCT 列名:计数指定列的唯一非空值行。
() t_student;
也可加入筛选条件,如求女学生数目:
() t_student student_sex;

( student_class) t_student;
DISTINCT即去重,如果不加DISTINCT则结果为表行数——5。
(student_age) t_student;
返回列平均值(AVG):
计算学生平均年龄:
(student_age) t_student;
返回最大值/最小值(MAX/MIN):
求年龄最大的学生信息(最小值同理):
(student_age) t_student;
注:这里只能求出最大年龄,要想显示年龄最大的学生全部信息,需要用到之后的子查询。
数据分组(GROUP BY):
SQL中数据可以按列名分组,搭配聚合函数十分实用。
例,统计每个班的人数:
student_class,( student_name) 总人数 t_student (student_class);
AS为定义别名,别名的使用在组合及联接查询时会有很好的效果,之后再说。
分组中也可以加入筛选条件WHERE,不过这里一定要注意的是,执行顺序为:WHERE过滤→分组→聚合函数。牢记!
统计每个班上20岁以上的学生人数:
student_class,(student_name) 总人数 t_student student_age (student_class);
HAVING过滤条件:
之前说了分组操作、聚合函数、WHERE过滤的执行顺序,那如果我们希望在聚合之后执行过滤条件怎么办?
例,我们想查询平均年龄在20岁以上的班级
能用下面的语句吗?
student_class, (student_age) t_student (student_age) student_class;
student_class,(student_age) 平均年龄 t_student (student_class) (student_age);



s.student_id,s.student_name,( class_name t_class c c.class_ids.class_id) t_student s s.student_id;
* 首先这条SQL语句用到了别名,写法为在FORM的表名后加上某个字符比如FROM t_student s,这样在之后调用t_student的某一列时就可以用s.student_id来强调此列来源于对应别名的那张表。
别名在子查询及联接查询中的应用有着很好效果,当两张表有相同列名或者为了加强可读性,给表加上不同的别名,就能很好的区分哪些列属于哪张表。
还有种情况就是在子查询或联接查询时,主查询及子查询均为对同一张表进行操作,为主、子查询中的表加上不同的别名能够很好的区分哪些列的操作是在主查询中进行的,哪些列的操作是在子查询中进行的,下文会有实例说明。


t_student student_subject student_score ( student_score t_student student_subject) ;
结果:
t_student student_subject student_score ( student_score t_student student_name student_subject);
通过上面两例,应该可以明白子查询在WHERE中嵌套的作用。通过子查询中返回的列值来作为比较对象,在WHERE中运用不同的比较运算符来对其进行比较,从而得到结果。
现在我们回到最开始的问题,怎么查出每门课最高成绩的学生的信息:
t_student s1 s1.student_score ( s2.student_score t_student s2 s1.`student_subject`s2.student_subject);
这里就是上文提到的别名的第二种用法,主、子查询对同一张表操作,区分开位于内外表中相同的列名。
结果:
子查询的分类:
组合查询:
通过UNION运算符来将两张表纵向联接,基本方式为:
列1 , 列2 列3 , 列4 表2;
UNION ALL为保留重复行:
列1 , 列2 列3 , 列4 表2;