(四) 结构化查询语言SQL——2

3)ORDER BY排序语句

通常,查询的结果是以无序的方式显示的,有时需要将查询结果按照一定次序来进行排序。ORDER BY就可以用上了,例如查询课程号为202的课程成绩的所有信息,并按照成绩降序排列

SELECT *

FROM SC

WHERE Cno = '202'

ORDER BY Grade DESC;(ASC代表升序,没有按ASC处理)

本来这个语句超简单,但是这货有个奇葩的共能就是能指定多个排序列,我TM……,比如这种:

SELECT *

FROM SC

WHERE Cno = '202'

ORDER BY Cno,Grade DESC;(经过查证,并非出现两个查询结果,而是先按照第一个排序规则排列,在第一个相同的情况下再按照下一个规则排序)

 

4)SQL函数

 COUNT 计数函数,基本形式 COUNT ([ALL|DISTINCT] *)用于返回查询结果元组的所有的个数或者不重复的个数。例如查询女生的数量

SELECT COUNT (*)

FROM Student

WHERE Sex = '女';

其实还蛮好记忆理解的,可以将COUNT也视为一种属性,即最终结果的个数,反正我就是这么理解的。

除此之外,还有求和SUM、平均值AVG、最大值MAX、最小值MIN等函数,基本形式与COUNT完全相同:<函数名称> ([ALL|DISTINCT] <值表达式>),所谓值表达式一般是指属性,比如查询数据结构课程的成绩平均值:
SELECT AVG (Grade)

FROM SC

WHERE Cname = '数据结构';

 

5)GROUP BY分组语句

GROUP BY主要是对记录进行分组,然后对每个分组使用聚集函数能够极大地提升效率(聚集函数+GROUP BY会使函数对分组进行相应的计算),其一般形式为:GROUP BY <分组列> {,<分组列>} [HAVING <分组选择条件>],那么HAVING的作用是对分组进行筛选,与WHERE不同,WHERE选择的是记录。例如查询每个学生的平均成绩,并输出平均成绩大于90的学生学号和平均成绩:

SELECT Sno,AVG(Grade)

FROM SC

GROUP BY Sno HAVING AVG(Grade) > 90;

 

6)连接查询

连接查询可以对多个表进行查询,即在FROM中包括多个表,这表示多个表的笛卡儿积,但是一般来说自然连接会更适合实际情况。例如查询学号为20142480135的学生各科成绩,显示每门课程的课程名和成绩。

SELECT Cname,Grade

FROM SC,Courses

WHERE SC.Cno = Courses.Cno AND SC.Sno = '20142480135';(思考红色部分和自然连接的关系)

 自身连接是和自己本身连接,通常情况使用不多,比如查询和武一鸣出生年月相同的学生的姓名:

SELECT B.Sname

FROM Student.A,Student.B

WHERE A.Birthday = B.Birthday AND

S1.Sname = '武一鸣' AND

S2.Sname <> '武一鸣';

用法是不是很奇葩?😰

 

7)嵌套查询

嵌套查询将一个查询嵌套在另一个SQL语句中,最常见的嵌套是子查询嵌套在父查询WHERE或者HAVING语句中,其中子查询不能使用ORDER BY子句。嵌套查询可以分两类:不相关子查询和相关子查询,前者子查询的条件不依赖于父查询,后者子查询条件依赖于父查询。嵌套查询表达式可以分为IN表达式、存在表达式、NULL表达式和唯一表达式。

IN表达式好像有点眼熟,在WHERE表达式中判断是否在集合中会用到IN,复习一下:

SELECT Sno,Sname

FROM Student

WHERE Speciality IN (‘计算机科学与技术’,‘软件工程’);

显然IN后面要紧跟一个集合,之前使用的都是显性的集合,实际上集合还可以是通过查询语句查询到的集合,例如

SELECT Sno,Sname

FROM Student

WHERE Speciality IN (

SELECT Speciality 

FROM Student

WHERE Sname = '武一鸣'

);

这里的集合是我的专业,如果我的专业是软件工程,那么这个SQL语句的作用就是查询软件工程所有学生的学号和姓名。当然这是没有人和我重名的情况下,否则就是另一个故事了。如果没人和我重名,代表子查询的结果只有一个值,可以将IN改为=,作用是相同的。这个示例是一个典型的不相关子查询。

 

SQL还允许将一个元素与子查询的结果集进行比较,这种量化的表达式常用形式是:<值表达式> θ ALL | SOME | ANY <子查询>,其中值表达式通常是属性,θ就是比较运算符,ANY和SOME的意义是一样的,当子查询结果是单个值时,ALL、SOME或者ANY可以省略。注意= SOME等价于IN,这也印证了前面单个值 = 等价于 IN的说法。

比如查询比软件工程专业所有学生都小的其他专业的学生学号、姓名和专业

SELECT Sno,Sname,Speciality

FROM Student

WHERE Birthday > ALL (

SELECT Bithday

FROM Student

WHERE Speciality = '软件工程');(原答案WHERE语句包括Speciality <> '软件工程' ,但是仔细一想其实是不必要的,因为软件工程怎么可能有一个年龄比所有人都小的学生,至少也不会比自己的年龄小)

事实上该语句可以改为:

SELECT Sno,Sname,Speciality

FROM Student

WHERE Birthday > (

SELECT MAX(Bithday)

FROM Student

WHERE Speciality = '软件工程');

聚集函数通常效率上相较于SOME和ALL会更高一些(但不能复合嵌套,例如MAX(AVG(…))的形式),它们的对应关系如下:

 

 

存在量词EXISTS

接下来就是整个SQL查询乃至整个SQL中最困难的部分——存在量词(我认为的@_@)。

一般形式:EXISTS <子查询>,接下来我就从EXISTS和IN的区别展开讲解吧。两者的区别主要在于执行顺序的不同,IN是先执行子查询,然后对结果在进行筛选,而EXISTS是先执行父查询,将查询的每个结果代入到子查询中进行检验,如果为TRUE,则保留,否则去除,最终的结果即为所求。

例如查询选修了全部课程的学生的学号和姓名:

SELECT Sno,Sname

FROM Student 

WHERE NOT EXISTS (

  SELECT *

  FROM Courses C

  WHERE NOT EXISTS (

    SELECT *

    FROM SC

    WHERE SC.Sno = S.Sno AND SC.Cno = C.Cno ) );

 

检查子查询结果中的重复元组

UNIQUE <子查询> 

查询只讲授一门课程教授的姓名

SELECT Tname

FROM Teacher T

WHERE UNIQUE (

  SELECT Tno

  FROM Teacher TC

  WHERE T.Tno = TC.Tno;)

这句话的逻辑在于对于父查询的每个结果执行子查询,若结果只有一个,那么保留该结果。

 

posted @ 2019-08-06 22:14  LeftBody  阅读(272)  评论(0编辑  收藏  举报