1.前提

在使用 SELECT 语句进行查询时,可以使用 WHERE 子句用来指定限制返回的行的搜索条件,GROUP BY子句将结果集分成组, ORDER BY 子句定义结果集中的行排列的顺序,使用这些子句可以检索出表中的数据,但是当 WHERE子句指定的检索条件指向另外一张表的时候,就需要使用到子查询或者嵌套查询

1.1 什么是子查询?

**
子查询是一个嵌套在 SELECT INSERT UPDATE DELETE语句或其他子查询中的查询,任何允许使用表达式的地方都可以使用子查询

关键字
**

  1. SELECT [ALL | DISTINCT] <search iitem list>
  2. FROM table_name
  3. WHERE <condition>
  4. GROUP BY <group_item_list>
  5. HAVING <group_by_search_condition>


语法规则
**

  • 子查询的 SELECT 查询总是使用圆括号括起来
  • 不能包括 COMPUTE 或 FOR BROWSE 子句
  • 如同同时指定 TOP 子句,则可能只包括 ORDER BY子句
  • 子查询最多可以支持32层,个别查询可能会不支持32层嵌套
  • 任何可以使用表达式的地方都可以使用子查询,只要他返回的是单个值
  • 如果某个表只出现在子查询中而不出现在外部查询中,那么表中的列就无法包含在输出中

语法格式
**

  • WHERE 查询表达式 [NOT] IN (子查询)
  • WHERE 查询表达式 比较运算符 [ANY | ALL] (子查询)
  • WHERE [NOT] EXISTS(子查询)

1.2什么是嵌套查询?

  1. 嵌套查询是指将一个查询嵌套在另外一个查询的 WHERE 子句或者 HAVING 短语的条件中的查询
  2. 嵌套查询的中上层查询块称为外侧查询或父查询,下层查询块称为内层查询或者子查询
  3. SQL语言允许多层嵌套,但是子查询中不允许出现 ORDER BY子句,ORDER BY子句只能处理出现在最外层的查询块中
  4. 处理嵌套查询的最后的方法就是:先处理最内侧的查询,然后一层一层的向上进行处理,知道最外层的查询块

2.嵌套查询

本部分可能使用到的3章表结构

CREATE TABLE Student
(
  Sno BIGINT UNIQUE PRIMARY KEY,
  Sname NCHAR(10) NOT NULL,
  Sex CHAR(2) DEFAULT '男',
  Sage int NOT NULL
)
CREATE TABLE Course
(
    Cno int identity PRIMARY KEY,
  Cname NVARCHAR(20) NOT NULL,
  Credit int NOT NULL
)

CREATE TABLE SC
(
    Sno BIGINT NOT NULL,
  Cno int NOT NULL,
  Grade int,
  ID INT identity PRIMARY KEY
)

2.1 简单的嵌套查询

用例
**

1.Student表中存储的是学生的基本信息,SC表 中存储的是学生的成绩信息,使用嵌套查询,查询在Student表中的 Grade > 90分的学生信息

SELECT * FROM Student WHERE Sno in (SELECT Sno FROM SC WHERE Grade > 90)

加上分数信息

SELECT Sname, S.Sno, Sex,Sage,Grade FROM Student S, SC 
WHERE S.Sno = SC.Sno
AND
SC.Grade > 90

2.2 带 in的嵌套查询

一些嵌套子查询有时会产生一个值,也有时会产生多个值,即子查询不能返回带几行和几列数据的表,原因在于子查询的结果必须适合外层查询的语句
当子查询产生了一系列的值以后,适合采取 IN 的嵌套查询

用例
**

1.在Student表中和Sc表中查询参加了任意一门考试的学生信息

SELECT * FROM Student WHERE Sno in (SELECT Sno FROM SC WHERE Grade is not null)

2.3带 not in 的嵌套查询

用例
**

1.在Student表中和Sc表中查询参加了全部考试的学生的信息

SELECT * FROM Student WHERE Sno not in (SELECT Sno FROM SC WHERE Grade is null)

2.4带 some,all,any的嵌套查询

用例
**

1.在Student表中,查询Sage小于平均年龄的所有学生信息

SELECT * FROM Student WHERE Sage < SOME (Select AVG(Sage) From Student)

2.在Student表中,查询Sage大于平均年龄的所有学生信息

SELECT * FROM Student WHERE Sage > ANY  (Select AVG(Sage) From Student)

3..在Student表中,查询Sage不等于平均年龄的所有学生信息

SELECT * FROM Student WHERE Sage <> ANY  (Select AVG(Sage) From Student)

4.在Student表中,查询不存在任意一门课程Grade没有大于90分的学生信息

SELECT * FROM Student WHERE Sno not in (select Sno from SC WHERE Grade > 90)
SELECT * FROM Student WHERE Sno <> ALL (select Sno from SC WHERE Grade > 90)

2.5带Exists的嵌套查询

Exists谓词只注重子查询是否返回行,如果子查询返回一个或多个行,谓词返回为真,否则则返回为假
Exists搜索条件并不真正的使用子查询的结果,他仅仅测试子查询中是否产生任何结果

用例
**

1.在Student表中查询参加考试的学生信息

SELECT * FROM Student WHERE EXISTS (SELECT Sno FROM SC WHERE Student.Sno = SC.Sno)

2.在Student表中查询没有参加任何一门考试的学生信息

SELECT * FROM Student WHERE NOT EXISTS (SELECT Sno FROM SC WHERE Student.Sno = SC.Sno)