ORDER BY 子句
可用在
WHERE子句
后
用户可以使用该子句对查询结果根据一个属性
或多个属性
列进行升序ASC
(Ascending 升序)或者降序DESC
(descend 降序)。
对于空值
,排序的次序由具体系统实现来决定。
默认值为ASC
(升序)。
一个属性
将学号大于105的学生的成绩表按学生成绩升序输出
1 | SELECT * FROM score WHERE sno>105 ORDER BY degree ASC |
多个属性
将成绩表按成绩降序、学号升序排序
多个属性时的优先度
为从左到右
1 | SELECT * FROM score ORDER BY degree DESC,sno ASC |
聚集函数
为了方便用户,增强检索功能,SQL提供了许多聚集函数:
函数 | 说明 |
---|---|
COUNT(*) | 统计元组个数 |
COUNT([DISTINCT|ALL] <别名>) | 统计一列中值的个数 |
SUM([DISTINCT|ALL] <别名>) | 计算一列值的总和 |
AVG([DISTINCT|ALL <别名>) | 计算一列值的平均值 |
MAX([DISTINCT|ALL <别名>) | 求某列的最大值 |
MIN([DISTINCT|ALL <别名>) | 求某列的最小值 |
- DISTINCT短语,表示在计算时取消指定列中的重复值。
- ALL短语,表示不取消重复值。
当聚合函数遇到列中的空值
时,都跳过
空值而只处理非空值
。
注意
- COUNT(*)是对元组进行计数,某个元组的一个或者部分取空值不影响COUNT的统计结果;
WHERE子句
中不能用聚集函数
作为条件表达式;聚集函数
只能用于SELECT子句
和GROUP BY子句
中的HAVING短语
GROUP BY 子句
将查询结果按某一列
或多列
的值分组,值相等的为一组
。
分组后聚集函数将作用于每一个组
,即每一组都有一个函数值。
结合HAVING
短语可进一步筛选结果。
某一列
求各班级的人数
1 | SELECT sclass,COUNT(*) FROM student GROUP BY sclass |
多列
求各班男女生的人数
1 | SELECT * FROM student; |
结合HAVING短语
查询人数小于15人的班级
1 | SELECT sclass,COUNT(*) FROM student GROUP BY sclass HAVING COUNT(*)<15 |
连接查询
同时涉及多张表
等值连接
一般格式
连接谓词为=
1 | SELECT <cl>,<c2>,... FROM <TB1>,<TB2>,... WHERE [TB1.]<列名1> = [<TB2.>]<列名2> = ... |
示例
1 | SELECT * FROM student,score WHERE student.sno=score.sno |
student表
score表
等值连接结果
非等值连接
连接谓词为其他运算符
<,>,>=,<=,!=,<>等等
自然连接
在等值连接中去除重复的属性列
1 | SELECT student.sno,sname,cno,grade |
自身连接
自身连接是一个表与其自己进行连接, 需要给表起别名AS
以示区别, 又由于所有属性名都是同名属性,因此必须使用别名前缀
外连接
外连接与普通连接的区别
普通连接操作只输出满足连接条件的元组;外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出
外连接又分为左连接
和``右外连接`
左连接
示例
1 | SELECT student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade |
说明
Student表
作为主体
,列出所有的元组(行),再将SC表
中的元组进行连接
右连接
示例
1 | SELECT sc.sno,Grade,course.cno,course.Cname,course.Ccredit |
说明
SC表
作为主体
,列出所有的元组(行),再将student表
中的元组进行连接
内连接
1 | SELECT |
在此语法中,从T1
和T2
表中查询检索数据:
- 首先,在
FROM
子句中指定主表(T1
) - 其次,在
INNER JOIN
子句和连接谓词中指定第二个表(T2
)。 只有连接谓词计算为TRUE
的行才包含在结果集中。
INNER JOIN
子句将表T1
的每一行与表T2
的行进行比较,以查找满足连接谓词的所有行对。 如果连接谓词的计算结果为TRUE
,则匹配的T1
和T2
行的列值将合并为一个新行并包含在结果集中。
下表说明了两个表T1(1,2,3)
和T2(A,B,C)
的内部连接。 结果包括行:(2,A)
和(3,B)
,因为它们具有相同的模式。
示例
多表连接
做法先对两个表进行连接,再将结果对第三个表进行连接
示例
1 | SELECT Student.Sno,Sname,Cname.Grade |
嵌套查询
在SQL中,一个SELECT-FROM-WHERE语句
称为一个查询块
,将一个查询块嵌套在另一个查询块的WHERE子句
或HAVING子句
中的查询,称为嵌套查询
。
注意
子查询的SELECT语句不能使用ORDER BY子句,ORDER BY子句只能为最终查询结果排序。
使用比较运算符
返回单个值的SELECT语句的嵌套查询
1 | SELECT * FROM [dbo].[Product] |
1 | SELECT * FROM [dbo].[Product] |
使用IN关键字
子查询结果往往是一个集合,谓词IN是嵌套查询中最长使用的谓词。
返回多个值的子查询的嵌套查询
1 | SELECT * FROM [dbo].[Product] |
上例的子查询使用INNER JOIN方式():
1 | SELECT [dbo].[Product].* FROM [dbo].[Product] |
出于性能方面的考虑
,如果没有特别的理由要使用嵌套的SELECT,则还是应使用连接方式作为默认的解决方案。
ANY(SOME)或ALL谓词
示例
查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄
1 | select Sname,Sage from student |
在处理执行此查询的时候,首先处理子查询,找出CS系中所有学生的年龄,构成集合,然后处理父查询,找所有不是CS系且年龄小于20或19的学生。
使用聚集函数来实现
1 | Select Sage,Sname from student |
查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名和年龄
1 | select Sname,Sage from student |
1 | Select Sage,Sname from student |
EXISTS关键字
EXISTS关键字后面的参数是一个任意的子查询,系统对子查询进行运算以判断它是否返回行,如果至少返回一行
,则EXISTS的结果为TRUE
,此时外层查询语句将进行查询;如果子查询没有返回任何行
,那么EXISTS返回
的结果是FALSE
,此时外层语句将不进行查询。
1 | SELECT * FROM [dbo].[Category] |