0
点赞
收藏
分享

微信扫一扫

《数据库》第3章 SQL查询语言(下)

_karen 2022-04-05 阅读 45

文章目录

3.4 嵌套子查询

在SQL查询中,一个

SELECT ...
FROM ...
WHERE ...

具体表现在如下几个方面:

  • 元素与集合间的属于关系
  • 集合之间的包含和相等关系
  • 集合的存在关系
  • 元素与集合元素之间的比较关系

嵌套查询分为相关子查询非相关子查询

  • 非相关子查询指子查询的结果不依赖于上层查询
  • 相关子查询指当上层查询的元组发生变化时,其子查询必须重新执行

注意:SQL允许多层嵌套子查询,但在子查询中不允许使用ORDER BY子句,该子句仅用于最后结果排序。

3.4.1 使用IN的子查询

单嵌套例子

--[例3.43] 查询选修过课程的学生姓名。
--本例查询的含义是:
--在学生表Student中,将学号出现在成绩表Score中(表明该学生选修过课程)的学生姓名查询出来
    SELECT studentName
    FROM Student
    WHERE Student.studentNo IN --其中Student.studentNo为元素,IN为"属于"
          (SELECT Score.studentNo FROM Score) 
 --嵌套语句“SELECT Score.studentNo FROM Score”的查询结果为选修过课程的所有学生的学号集合

从Student表取出元组逐一与子嵌套表的结果集合比较,在则作为查询结果,否则丢弃,直到Student表为空。
具体看图
在这里插入图片描述

多重嵌套例子

--[例3.44] 查找选修过课程名中包含“系统”的课程的同学学号、姓名和班级编号。
SELECT studentNo, studentName, classNo
FROM Student
WHERE studentNo IN 
                 ( SELECT studentNo FROM Score
                    WHERE courseNo IN 
                                     ( SELECT courseNo FROM Course
                                        WHERE courseName LIKE '%系统%' )
                 )
-- 等价于
SELECT studentNo, studentName, classNo
FROM Student
WHERE studentNo IN 
                 ( SELECT studentNo 
                    FROM Score b, Course c
                    WHERE b.courseNo=c.courseNo 
                          AND courseName LIKE '%系统%' 
                 )
--等价于
SELECT DISTINCT studentNo, studentName, classNo
FROM Student a, Score b, Course c
WHERE a.studentNo=b.studentNo
       AND b.courseNo=c.courseNo 
       AND courseName LIKE '%系统%' 

多重嵌套从最底层开始执行,执行过程跟单嵌套一样
在这里插入图片描述
在这里插入图片描述

--[例3.45] 查找同时选修过“计算机原理”和“高等数学”两门课程的同学学号、姓名以及该同学所选修的所有课程的课程名和相应成绩,按学号(升序)、成绩(降序)排序输出。
SELECT  a.studentNo, studentName, courseName, score
FROM Student a, Course b, Score c
WHERE  a.studentNo=c.studentNo AND b.courseNo=c.courseNo
	-- 选修过“计算机原理”课程的学号,使用双重嵌套,也可以用单嵌套利用等值连接SELECT studentNo FROM Score x, Course y WHERE x.courseNo=y.courseNo AND courseName='计算机原理')
      AND   a.studentNo IN 
                  ( SELECT studentNo FROM Score
                     WHERE courseNo IN 
                                      ( SELECT courseNo FROM Course
                                         WHERE courseName='计算机原理' ) ) 
	-- 选修过“高等数学”课程的学号
      AND   a.studentNo IN 
                  ( SELECT studentNo FROM Score
                     WHERE courseNo IN 
                                      ( SELECT courseNo FROM Course
                                         WHERE courseName='高等数学' ) ) 
ORDER BY a.studentNo, score DESC

如果这道题变成查找同时选修过“计算机原理”和“高等数学”两门课程的同学学号、姓名以及所选修的这两门课程的课程名和相应成绩,按学号(升序)、成绩(降序)排序输出。
那要在WHERE子句中再加一句AND ( b.courseName=‘高等数学’ OR b.courseName=‘计算机原理’ ),相当于在所有课程选出来之后挑选高等数学的还有计算机原理的

3.4.2 使用比较运算符的子查询

--[例3.47] 查询所选修课程的成绩大于所有002号课程成绩的同学学号及相应课程的课程号和成绩。
SELECT studentNo, courseNo, score
FROM Score
WHERE score>ALL
                 ( SELECT score
                   FROM Score
                   WHERE courseNo='002' )
--[例3.48] 查询成绩最高分的学生的学号、课程号和相应成绩
SELECT studentNo, courseNo, score
FROM Score
WHERE score=( SELECT max(score)
                              FROM Score )

聚合函数注意点

聚合函数可直接用在HAVING子句中(如例3.35)
聚合函数也可用于子查询中(如例3.48),
聚合函数不可以直接使用在WHERE子句中。如
SELECT *
FROM Score
WHERE score=max(score)         ×

*3.4.3 使用存在量词EXISTS的子查询

  • 一是存在量词,使用谓词EXISTS表示(在WHERE子句中使用谓词EXISTS用来判断其后的子查询的结果集合中是否存在元素)
  • 二是全称量词,转化通过NOT EXISTS谓词来实现。(双重否定为肯定)

谓词EXISTS大量用于相关子查询中

--[例3.51] 查询选修了所有课程的学生姓名。
SELECT studentName 
FROM Student x
WHERE NOT EXISTS 
                 ( SELECT * FROM Course c
                    WHERE NOT EXISTS   
                                     --判断学生x.studentNo没有选修课程c.courseNo
                                     ( SELECT * FROM Score
                                        WHERE studentNo=x.studentNo 
                                               AND courseNo=c.courseNo )
                 )

3.5 集合查询

并UNION

--[例3.57] 查询“信息管理学院”1999年出生的同学的学号、出生日期、班级名称和所属学院以及“会计学院”1998年出生的同学的学号、出生日期、班级名称和所属学院。
SELECT studentNo, birthday, className, institute
FROM Student a, Class b
WHERE a.classNo=b.classNo AND year(birthday)=1999 
       AND institute='信息管理学院'
UNION
SELECT studentNo, birthday, className, institute
FROM Student a, Class b
WHERE a.classNo=b.classNo AND year(birthday)=1998 
       AND institute='会计学院'

交INTERSECT

--[例3.58] 查询同时选修了“001”号和“005”号课程的同学的学号和姓名
SELECT a.studentNo, studentName
FROM Student a, Score b
WHERE a.studentNo=b.studentNo AND courseNo='001'
INTERSECT
SELECT a.studentNo, studentName
FROM Student a, Score b
WHERE a.studentNo=b.studentNo AND courseNo='005'

差EXCEPT

--[例3.59] 查询没有选修“计算机原理”课程的同学的学号和姓名。
SELECT studentNo, studentName
FROM Student
EXCEPT
SELECT DISTINCT a.studentNo, studentName
FROM Student a, Score b, Course c
WHERE a.studentNo=b.studentNo 
      AND  b.courseNo=c.courseNo 
      AND  courseName='计算机原理'
举报

相关推荐

SQL数据库——连接查询

0 条评论