ORDER BY 子句

可用在WHERE子句

用户可以使用该子句对查询结果根据一个属性多个属性列进行升序ASC

(Ascending 升序)或者降序DESC(descend 降序)。

对于空值,排序的次序由具体系统实现来决定。

默认值为ASC(升序)。

一个属性

将学号大于105的学生的成绩表按学生成绩升序输出

1
2
3
SELECT * FROM score WHERE sno>105 ORDER BY degree ASC
-- 省略ASC
SELECT * FROM score WHERE sno>105 ORDER BY degree

image-20220813175602717

多个属性

将成绩表按成绩降序、学号升序排序

多个属性时的优先度从左到右

1
SELECT * FROM score ORDER BY degree DESC,sno ASC

image-20220813175229695

聚集函数

为了方便用户,增强检索功能,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

image-20220813192008924

多列

求各班男女生的人数

1
2
SELECT * FROM student;
SELECT sclass,ssex,COUNT(*) FROM student GROUP BY sclass,ssex

image-20220813193110140

结合HAVING短语

查询人数小于15人的班级

1
SELECT sclass,COUNT(*) FROM student GROUP BY sclass HAVING COUNT(*)<15 

image-20220813194128038

连接查询

同时涉及多张表

等值连接

一般格式

连接谓词为=

1
2
3
SELECT <cl>,<c2>,... FROM <TB1>,<TB2>,... WHERE [TB1.]<列名1> = [<TB2.>]<列名2> = ...
-- 还可以使用BETWEEN作为连接谓词
SELECT <cl>,<c2> FROM <TB1>,<TB2>,<TB3> WHERE [TB1.]<列名1> BETWEEN [<TB2.>]<列名2> AND [<TB3.>]<列名3>

示例

1
SELECT * FROM student,score WHERE student.sno=score.sno

student表

image-20220813201828327

score表

image-20220813201919626

等值连接结果

image-20220813201420782

非等值连接

连接谓词为其他运算符

<,>,>=,<=,!=,<>等等

自然连接

在等值连接中去除重复的属性列

1
2
SELECT student.sno,sname,cno,grade
FROM Student,SC where (Student.Sno=SC.Sno);

自身连接

自身连接是一个表与其自己进行连接, 需要给表起别名AS以示区别, 又由于所有属性名都是同名属性,因此必须使用别名前缀

外连接

外连接与普通连接的区别

普通连接操作只输出满足连接条件的元组;外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出

外连接又分为左连接和``右外连接`

左连接

示例

1
2
SELECT student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student LEFT OUTER JOIN SC ON (Student.Sno=SC.Sno);

说明

Student表作为主体,列出所有的元组(行),再将SC表中的元组进行连接

右连接

示例

1
2
SELECT sc.sno,Grade,course.cno,course.Cname,course.Ccredit
FROM SC right OUTER JOIN course ON (sc.Cno=Course.Cno);

说明

SC表作为主体,列出所有的元组(行),再将student表中的元组进行连接

内连接

1
2
3
4
5
SELECT
select_list
FROM
T1
INNER JOIN T2 ON join_predicate;

在此语法中,从T1T2表中查询检索数据:

  • 首先,在FROM子句中指定主表(T1)
  • 其次,在INNER JOIN子句和连接谓词中指定第二个表(T2)。 只有连接谓词计算为TRUE的行才包含在结果集中。

INNER JOIN子句将表T1的每一行与表T2的行进行比较,以查找满足连接谓词的所有行对。 如果连接谓词的计算结果为TRUE,则匹配的T1T2行的列值将合并为一个新行并包含在结果集中。

下表说明了两个表T1(1,2,3)T2(A,B,C)的内部连接。 结果包括行:(2,A)(3,B),因为它们具有相同的模式。

示例

多表连接

做法先对两个表进行连接,再将结果对第三个表进行连接

示例

1
2
3
SELECT Student.Sno,Sname,Cname.Grade
FROM Student,SC,Course
WHERE Student.sno=SC.sno AND SC.cno=Course.cno

嵌套查询

在SQL中,一个SELECT-FROM-WHERE语句称为一个查询块,将一个查询块嵌套在另一个查询块的WHERE子句HAVING子句中的查询,称为嵌套查询

注意

子查询的SELECT语句不能使用ORDER BY子句,ORDER BY子句只能为最终查询结果排序。

使用比较运算符

返回单个值的SELECT语句的嵌套查询

1
2
3
4
SELECT * FROM [dbo].[Product]
WHERE [UnitPrice] = (
SELECT MIN([UnitPrice]) FROM [dbo].[Product]
)
1
2
3
4
5
6
SELECT * FROM [dbo].[Product]
WHERE [CategoryID] =
(
SELECT [CategoryID] FROM [dbo].[Category]
WHERE [CategoryName] = 'LINQ to SQL'
)

使用IN关键字

子查询结果往往是一个集合,谓词IN是嵌套查询中最长使用的谓词。

返回多个值的子查询的嵌套查询

1
2
3
4
5
SELECT * FROM [dbo].[Product]
WHERE [CategoryID] IN (
SELECT [CategoryID] FROM [dbo].[Category]
WHERE [CategoryID] <= 10
)

上例的子查询使用INNER JOIN方式():

1
2
3
SELECT [dbo].[Product].* FROM [dbo].[Product]
INNER JOIN [dbo].[Category] ON [dbo].[Product].[CategoryID] = [dbo].[Category].[CategoryID]
WHERE [dbo].[Category].[CategoryID] <= 10

出于性能方面的考虑,如果没有特别的理由要使用嵌套的SELECT,则还是应使用连接方式作为默认的解决方案。

ANY(SOME)或ALL谓词

image-20220813212046929

示例

查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄

1
2
3
4
select Sname,Sage from student 
where Sage < ANY(select Sage from student
where Sdept = "CS")
AND Sdept <> "CS";

在处理执行此查询的时候,首先处理子查询,找出CS系中所有学生的年龄,构成集合,然后处理父查询,找所有不是CS系且年龄小于2019的学生。

使用聚集函数来实现
1
2
3
4
Select Sage,Sname from student 
where Sage < (select MAX(Sage) from Student
where Sdept= 'CS')
AND Sdept != 'CS'

查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名和年龄

1
2
3
4
select Sname,Sage from student 
where Sage < ALL (select Sage from student
where Sdept = "CS")
AND Sdept <> "CS";
1
2
3
4
 Select Sage,Sname from student
where Sage < (select MIN(Sage) from Student
where Sdept= 'CS')
AND Sdept != 'CS'

EXISTS关键字

EXISTS关键字后面的参数是一个任意的子查询,系统对子查询进行运算以判断它是否返回行,如果至少返回一行,则EXISTS的结果为TRUE,此时外层查询语句将进行查询;如果子查询没有返回任何行,那么EXISTS返回的结果是FALSE,此时外层语句将不进行查询。

1
2
3
4
5
SELECT * FROM [dbo].[Category]
WHERE EXISTS (
SELECT * FROM [dbo].[Product]
WHERE [CategoryID] = 1
)