大脚骨手术风险:第13章 嵌套查询

来源:百度文库 编辑:中财网 时间:2024/04/30 06:19:15

第13章 嵌套查询

当一个查询是另一个查询的条件时,就称之为嵌套查询,又称为子查询。嵌套查询可以使用几个简单的命令构造功能强大的复合查询命令。嵌套查询最常用于SQL语句的WHERE子句中,按照嵌套查询返回值是单个值还是一组值,查询一个表还是多个表,嵌套查询有不同的形式,介绍几种常见的嵌套查询。

13.1 嵌套查询的语法结构

嵌套查询一般包括以下一些组成部分:标准的SELECT语句、一个或多个表的FROM子句、可选的WHERE子句、可选的GROUP BY子句和可选的HAVING子句。

在含有嵌套查询的语句中,嵌套查询问题用圆括号括起来,并且嵌套查询最多嵌套32层。此外,嵌套查询中不能包括COMPUTER子句或者FORBROWSE子句。

一个简单的嵌套查询语句如下所示:

SELECT * FROM 成绩

  WHERE 成绩>(SELECT AVG(成绩) FROM 成绩)

这个语句就是要查询成绩高于平均成绩的所有记录。

13.2 返回单值的嵌套查询

这里所说的简单嵌套查询,是指嵌套查询的返回值是一个,并作为WHERE子句的条件值。例如,上面介绍的查询成绩高于平均成绩的所有记录的嵌套查询,就是一个简单的嵌套查询例子。

【例13-1】下面的例子是从数据库“研究生管理”中的数据表“成绩”中,查询所有成绩高于平均成绩的学生考试记录信息。

在运行下面的程序之前,要确保已经引用了ADO对象库MicrosoftActive Data Objects 2.5 Library或其他版本(如Microsoft Active Data Objects 2.1 Library、Microsoft Active Data Objects 2.8 Library等)。同时,还要根据电脑实际情况,将连接字符串中的SQL Server服务器名称进行变更,并输入相应的用户名和密码(如果有的话)。

Public Sub 例13—1()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

  Dim SQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

   SQL = " select * from 成绩" _

      & " where 成绩>(select avg(成绩) from 成绩) "

   Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   For i = 0 To rs.Fields.Count - 1 '复制字段名

       Cells(1, i + 1) = rs.Fields(i).Name

       Cells(1, i + 1).Font.Bold = True

   Next i

   Range("A2").ColumnDifferences rs   '复制查询出的数据

   Columns.AutoFit

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

运行程序后的结果如图13-1所示的结果。

【例13-2】图13-1所示的所有成绩高于平均成绩的学生记录信息,信息不是很明确,例如不知道学生的具体姓名、课程的具体名称等。下面的例子是从数据库“研究生管理”中的数据表“成绩”、“研究生”和“课程”中,查询所有成绩高于平均成绩的学生记录信息,包括姓名、性别、班级、课程名称和成绩等。

Public Sub 例13—2()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

  Dim SQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

   SQL = " select 研究生.姓名,研究生.性别,课程.课程名称,成绩.成绩" _

      & "from 研究生,课程,成绩" _

      & " where 研究生.学号=成绩.学号 and 成绩.课程代码=课程.课程代码 "_

      & "and 成绩.成绩>(selectavg(成绩.成绩) from 成绩)"

   Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   For i = 0 To rs.Fields.Count - 1 '复制字段名

       Cells(1, i + 1) = rs.Fields(i).Name

       Cells(1, i + 1).Font.Bold = True

   Next i

   Range("A2").ColumnDifferences rs   '复制查询出的数据

   Columns.AutoFit

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

运行程序后的结果如图13-2所示。

【例13-3】下面的例子是从数据库“研究生管理”中的数据表“成绩”、“研究生”和“课程”中,查询“微观材料学”课程的所有成绩高于平均成绩的学生记录信息,包括姓名、性别、班级、课程名称和成绩等。

Public Sub 例13—3()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

  Dim SQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

   SQL = " select 研究生.姓名,研究生.性别,课程.课程名称,成绩.成绩" _

      & "from 研究生,课程,成绩" _

      & " where 研究生.学号=成绩.学号 and 成绩.课程代码=课程.课程代码 "_

      & "and 成绩.成绩>(selectavg(成绩.成绩) from 成绩 where 课程.课程名称=‘微观材料学’)"

   Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   For i = 0 To rs.Fields.Count - 1 '复制字段名

       Cells(1, i + 1) = rs.Fields(i).Name

       Cells(1, i + 1).Font.Bold = True

   Next i

   Range("A2").ColumnDifferences rs   '复制查询出的数据

   Columns.AutoFit

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

运行程序后的结果如图13-3所示。

【例13-4】下面的例子是从数据库“研究生管理”中的数据表“成绩”、“研究生”和“课程”,“导师”中,教师“李辉”授课的学生成绩记录,包括姓名、性别、班级、课程名称和成绩等,并按成绩从高到低排序。

Public Sub 例13—4()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

  Dim SQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

   SQL = " select 研究生.姓名 as 研究生姓名,研究生.性别,课程.课程名称,成绩.成绩,导师.姓名 as 导师姓名"_

      & "from 研究生,导师,课程,成绩" _

      & " where 研究生.学号=成绩.学号 and 成绩.课程代码=课程.课程代码 "_

      & "and 成绩.课程代码=(select课程.课程代码 from 导师, 课程)" _

      & "where 导师.导师编号=课程.授课教师 and 导师.姓名=‘李辉’)"

   Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   For i = 0 To rs.Fields.Count - 1 '复制字段名

       Cells(1, i + 1) = rs.Fields(i).Name

       Cells(1, i + 1).Font.Bold = True

   Next i

   Range("A2").ColumnDifferences rs   '复制查询出的数据

   Columns.AutoFit

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

运行程序后的结果如图13-4所示。

13.3 返回多值的嵌套查询

前面介绍的嵌套查询是返回单值,也就是返回表中的某一行。如果嵌套查询的返回值是表中的多行记录,那么就需要在WHERE子句中使用IN(NOTIN)、SOME(ANY)、ALL和EXISTS(NOT EXISTS)等关键字。

13.3.1 IN(NOT IN)嵌套查询

IN(NOT IN)关键字构建的嵌套查询,是在WHERE子句中使用IN(NOT IN)来判断在嵌套查询的返回值列表中是否有满足条件的记录,IN表示要判断是否有满足条件的记录,NOT IN 表示要判断是否没有满足条件的记录。

【例13-5】下面的例子是从数据库“研究生管理”中,查询出存在有95分以上成绩的不重复的课程名称。

Public Sub 例13—5()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

  Dim SQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

   SQL = " select distinct 课程.课程名称 from 课程,成绩" _

      & "where 成绩.成绩 in(select 成绩 from 成绩 where 成绩>95)"

   Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   Range("A1") = Array("课程名称")

   Range("A2").ColumnDifferences rs

   Columns.AutoFit

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

运行程序后的结果如图13-5所示。

【例13-6】下面的例子是从数据库“研究生管理”中,查询出平均分在85分以上成绩的课程名称。

Public Sub 例13—6()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

  Dim SQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

   SQL = " select 课程名称 from 课程 " _

      & "where 课程代码 in " _

      & "(select 课程代码 from 成绩 " _

      & "group by 课程代码 having(avg(成绩))>85)"

   Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   Range("A1") = Array("平均分在85分以上的课程名称")

   Range("A2").CopyFromRecordset rs

   Columns.AutoFit

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

运行程序后的结果如图13-6所示。

【例13-7】下面的例子是从数据库“研究生管理”中,查询出平均分在85分以下成绩的课程名称。

Public Sub 例13—7()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

  Dim SQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

   SQL = " select 课程名称 from 课程 " _

      & "where 课程代码 not in " _

      & "(select 课程代码 from 成绩 group by课程代码 having(avg(成绩))>85)"

    Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   Range("A1") = Array("平均分在85分以下的课程名称")

   Range("A2").CopyFromRecordset rs

   Columns.AutoFit

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

运行程序后的结果如图13-7所示。

13.3.2 SOME(ANY)嵌套查询

SOME(ANY)嵌套查询是指在嵌套查询的返回值列表中,只取比较结果为TRUE的结果。SOME(ANY)的语法结构如下:

表达式比较运算符 SOME (或ANY) (嵌套查询)

【例13-8】下面的例子是从数据库“研究生管理”中,查询选修编号为“200601003”课程、并且考试分数不高于学号为“A03200602”的学生的姓名、性别及考试成绩,并按成绩降序排列。

Public Sub 例13—8()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

  Dim SQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

   SQL = " select 学号,课程名称,成绩 from 成绩 " _

      & "where 课程代码 =‘200601003’ " _

      & "and 成绩03200602’)"_

      & "order by 成绩 desc"

   Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   Range("A1:C1") = Array("学号","课程代码", "成绩")

   Range("A1:C1").Font.Bold = True

   Range("A2").CopyFromRecordset rs

   Columns.AutoFit

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

运行程序后的结果如图13-8所示。

13.3.3 ALL嵌套查询

是指在嵌套查询的返回值列表中,只取比较结果都为TRUE的结果。ALL的语法结构如下:

表达式比较运算符 ALL (嵌套查询)

【例13-9】下面的例子是从数据库“研究生管理”中,查询选修编号为“200601003”课程、并且考试分数低于所有学号为“A03200603”的学生的姓名、性别及考试成绩,并按成绩降序排列。

Public Sub 例13—9()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

   DimSQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

   SQL = " select 学号,课程名称,成绩 from 成绩 " _

      & "where 课程代码 =‘200601003’ " _

      & "and 成绩03200602’)"_

      & "order by 成绩 desc"

   Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   Range("A1:C1") = Array("学号","课程代码", "成绩")

   Range("A1:C1").Font.Bold = True

   Range("A2").CopyFromRecordset rs

   Columns.AutoFit

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

运行程序后的结果如图13-9所示。

13.3.4 EXISTS(NOT EXISTS)嵌套查询

是指通过检测嵌套查询的返回值列表,只要有一个满足条件就返回其值。

【例13-10】下面的例子是从数据库“研究生管理”中,查询出所有任课教师的姓名、性别和在院系等信息。

Public Sub 例13—10()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

  Dim SQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

   SQL = " select A.姓名,A.性别,B.院系名 from 导师 as A,院系 as B" _

      & "where A.院系编号=B.院系编号 "_

      & "and exists (select * from 课程 as Cwhere C.授课教师=A.导师编号)"

   Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   Range("A1:C1") = Array("姓名","性别", "院系")

   Range("A1:C1").Font.Bold = True

   Range("A2").CopyFromRecordset rs

   Columns.AutoFit

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

运行程序后的结果如图13-10所示。

13.4 多层嵌套查询

嵌套查询自身可以包含一个或多个嵌套查询,这就是多层嵌套查询。

【例13-11】下面的例子是从数据库“研究生管理”中,查询最高分数的学生姓名。

Public Sub 例13—11()

  Dim cnn As New ADODB.Connection

  Dim rs As ADODB.Recordset

  Dim SQL As String

   '建立与SQL Server服务器的连接

  cnn.ConnectionString = "Provider=SQLOLEDB;" _

       & "User ID=sa;" _

       & "password=11111;" _

       & "Data Source=THTFCOMPUTER;" _

       & "Initial Catalog=研究生管理"

   cnn.Open

    '查询数据

    SQL= " select 姓名 from 研究生 where 学号 in " _

      & "(select 学号 from 成绩 where 成绩=(select max(成绩) from 成绩))"

   Set rs = cnn.Execute(SQL)

    '复制查询出的数据

   Cells.Clear

   Range("A1") = Array"姓名"

   Range("A1:C1").Font.Bold = True

   Range("A2").CopyFromRecordset rs

    '关机记录集以及与数据库的连接

   cnn.Close

   Set rs = Nothing

   Set cnn = Nothing

End Sub

这里在主查询SELECT语句的WHERE子句中使用IN关键字,是因为可能有几个相同的最高成绩。