SQL Server的子查询详解

目录
  • 一、子查询基础知识
  • 二、子查询规则
  • 三、限定子查询中的列名
  • 四、子查询的多层嵌套
  • 五、相关子查询
  • 六、子查询类型
  • 总结

一、子查询基础知识

子查询是嵌套在SELECT、INSERT、UPDATE、DELETE语句中或另一个子查询中的查询。
可以在允许表达式的任何位置使用子查询。

示例:

USE AdventureWorks2016;
GO
SELECT Ord.SalesOrderID, Ord.OrderDate,
    (SELECT MAX(OrdDet.UnitPrice)
     FROM Sales.SalesOrderDetail AS OrdDet
     WHERE Ord.SalesOrderID = OrdDet.SalesOrderID) AS MaxUnitPrice
FROM Sales.SalesOrderHeader AS Ord;
GO

子查询也称为内部查询或内部选择,而包含子查询的语句也称为外部查询或外部选择。

许多包含子查询的 Transact-SQL 语句也可以表述为联接。其他问题只能用子查询提出。在 Transact-SQL 中,包含子查询的语句与不包含子查询的语义等效版本之间通常没有性能差异。但是,在某些必须检查是否存在的情况下,联接会产生更好的性能。否则,必须为外部查询的每个结果处理嵌套查询,以确保消除重复项。在这种情况下,联接方法将产生更好的结果。

以下示例显示了返回相同结果集和执行计划的子查询和联接:

USE AdventureWorks2016;
GO

/* SELECT statement built using a subquery. */
SELECT [Name]
FROM Production.Product
WHERE ListPrice =
    (SELECT ListPrice
     FROM Production.Product
     WHERE [Name] = 'Chainring Bolts' );
GO

/* SELECT statement built using a join that returns
   the same result set. */
SELECT Prd1.[Name]
FROM Production.Product AS Prd1
     JOIN Production.Product AS Prd2
       ON (Prd1.ListPrice = Prd2.ListPrice)
WHERE Prd2.[Name] = 'Chainring Bolts';
GO

嵌套在外部 SELECT 语句中的子查询具有以下组件:

  • 包含常规选择列表组件的常规查询。
  • 包含一个或多个表或视图名称的常规子句。
  • 可选:WHERE、GROUP BY、HAVING。

子查询的 SELECT 查询始终括在括号中。它不能包含 or 子句,并且只能在还指定 TOP 子句时才包含子句。

子查询可以嵌套在外部 WHERE、HAVING、SELECT、INSERT、UPDATE、DELETE或语句的 or 子句中,也可以嵌套在另一个子查询中。最多可以嵌套 32 个级别,但限制因可用内存和查询中其他表达式的复杂性而异。单个查询可能不支持嵌套多达 32 个级别。如果子查询返回单个值,则子查询可以出现在可以使用表达式的任何位置。

如果表仅出现在子查询中而不出现在外部查询中,则该表中的列不能包含在输出(外部查询的选择列表)中。

包含子查询的语句通常采用以下格式之一:

  • WHERE expression [NOT] IN (subquery)
  • WHERE expression comparison_operator [ANY | ALL] (subquery)
  • WHERE [NOT] EXISTS (subquery)

在某些 Transact-SQL 语句中,可以像计算独立查询一样计算子查询。从概念上讲,子查询结果被替换到外部查询中(尽管这不一定是 SQL Server 实际处理带有子查询的 Transact-SQL 语句的方式)。

有三种基本类型的子查询:

对引入的列表进行操作,或者比较运算符由 INANY或ALL 修改的列表。
使用未修改的比较运算符引入,并且必须返回单个值。
是否使用EXISTS引入存在性测试。

二、子查询规则

  • 使用比较运算符引入的子查询的选择列表只能包含一个表达式或列名。
  • 如果外部查询的子句包含列名,则该子句必须与子查询选择列表中的列连接兼容。
  • ntext、text 和 image 数据类型不能在子查询的选择列表中使用。
  • 由于它们必须返回单个值,因此由未修改的比较运算符(不后跟关键字或)引入的子查询不能包含 and 子句。
  • 关键字不能与包含 的子查询一起使用。
  • 不能指定 and 子句。
  • ORDER BY只有在也指定TOP时才能指定。
  • 无法使用子查询创建的视图进行更新。

三、限定子查询中的列名

示例:外部查询子句中的 BusinessEntityID 列由外部查询子句 (Sales.Store) 中的表名隐式限定。子查询的选择列表中对 CustomerID 的引用由子查询子句(即 Sales.Customer 表)限定。

USE AdventureWorks2016;
GO
SELECT [Name]
FROM Sales.Store
WHERE BusinessEntityID NOT IN
    (SELECT CustomerID
     FROM Sales.Customer
     WHERE TerritoryID = 5);
GO

一般,语句中的列名由同一级别的子句中引用的表隐式限定。如果子查询子句中引用的表中不存在列,则外部查询子句中引用的表将隐式限定该列。

下面是指定这些隐式假设的查询的外观:

USE AdventureWorks2016;
GO
SELECT [Name]
FROM Sales.Store
WHERE Sales.Store.BusinessEntityID NOT IN
    (SELECT Sales.Customer.CustomerID
     FROM Sales.Customer
     WHERE TerritoryID = 5);
GO

显式声明表名永远不会错,并且始终可以使用显式限定覆盖有关表名的隐式假设。

四、子查询的多层嵌套

子查询本身可以包含一个或多个子查询。任意数量的子查询可以嵌套在一个语句中。

示例:查询查找同时也是销售人员的员工的姓名。

USE AdventureWorks2016;
GO
SELECT LastName, FirstName
FROM Person.Person
WHERE BusinessEntityID IN
    (SELECT BusinessEntityID
     FROM HumanResources.Employee
     WHERE BusinessEntityID IN
        (SELECT BusinessEntityID
         FROM Sales.SalesPerson)
    );
GO

输出:

最里面的查询返回销售人员 ID。下一个更高级别查询使用这些销售人员 ID 进行评估,并返回员工的联系人 ID 号。最后,外部查询使用联系人 ID 查找员工的姓名。

还可以将此查询表示为联接:

USE AdventureWorks2016;
GO
SELECT LastName, FirstName
FROM Person.Person c
INNER JOIN HumanResources.Employee e
ON c.BusinessEntityID = e.BusinessEntityID
JOIN Sales.SalesPerson s
ON e.BusinessEntityID = s.BusinessEntityID;
GO

五、相关子查询

可以通过执行一次子查询并将结果值替换到外部查询的子句中来计算许多查询。在包含相关子查询(也称为重复子查询)的查询中,子查询依赖于其值的外部查询。这意味着子查询将重复执行,外部查询可能选择的每一行执行一次。

示例:

USE AdventureWorks2016;
GO
SELECT DISTINCT c.LastName, c.FirstName, e.BusinessEntityID
FROM Person.Person AS c JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = c.BusinessEntityID
WHERE 5000.00 IN
    (SELECT Bonus
    FROM Sales.SalesPerson sp
    WHERE e.BusinessEntityID = sp.BusinessEntityID) ;
GO

输出结果:

此语句中的上一个子查询不能独立于外部查询进行计算。它需要 Employee.BusinessEntityID 的值,但此值会随着 SQL Server 检查 Employee 中的不同行而更改。 这正是计算此查询的方式:SQL Server 通过将每行中的值替换为内部查询来考虑将 Employee 表的每一行包含在结果中。 例如,如果 SQL Server 首先检查 的行,则变量 Employee.BusinessEntityID 采用值 285,SQL Server 将其替换到内部查询中。这两个查询示例表示具有相关子查询的前一个示例的分解。

USE AdventureWorks2016;
GO
SELECT Bonus
FROM Sales.SalesPerson
WHERE BusinessEntityID = 285;
GO

结果为 0.00(没有收到奖金,因为他们不是销售人员),因此外部查询的计算结果为:

USE AdventureWorks2016;
GO
SELECT LastName, FirstName
FROM Person.Person AS c JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = c.BusinessEntityID
WHERE 5000 IN (0.00);
GO

由于这是 false,因此 的行不包含在具有相关子查询的上一个示例查询的结果中。对 的行执行相同的过程。您将看到此行包含在结果中,因为包含结果。

小结:相关子查询还可以通过在外部查询中引用表中的列作为表值函数的参数,在子句中包含表值函数。在这种情况下,对于外部查询的每一行,将根据子查询计算表值函数。

六、子查询类型

  • 带别名。
  • 带IN或NOT IN。
  • 在UPDATE、DELETE 和 INSERT 语句中。
  • 使用比较运算符。
  • 使用 ANY、SOME 或 ALL。
  • 跟 IS [NOT] DISTINCT FROM。
  • 带 EXISTS或 NOT EXISTS。
  • 代替表达式。

总结

如果在子查询中引用的列在子查询中不存在,但存在于外部查询的子句引用的表中,则查询将执行而不会出错。SQL Server 使用外部查询中的表名隐式限定子查询中的列。

到此这篇关于SQL Server的子查询详解的文章就介绍到这了,更多相关SQL Server子查询内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 使用SQL Server数据库嵌套子查询的方法

    很多SQL Server程序员对子查询(subqueries)的使用感到困惑,尤其对于嵌套子查询(即子查询中包含一个子查询).现在,就让我们追本溯源地探究这个问题.  有两种子查询类型:标准和相关.标准子查询执行一次,结果反馈给父查询.相关子查询每行执行一次,由父查询找回.在本文中,我将重点讨论嵌套子查询(nested subqueries)(我将在以后介绍相关子查询).  试想这个问题:你想生成一个卖平垫圈的销售人员列表.你需要的数据分散在四个表格中:人员.联系方式(Person.Contac

  • 在SQL Server中使用子查询更新语句

    测试环境准备 create table #table1 ( id int , name varchar(20) ); go create table #table2 ( id int , name varchar(20) ); go insert into #table1 ( id, name ) values ( 1, 'a' ), ( 2, null ), ( 3, 'c' ), ( 4, 'd' ), ( 5, 'e' ); insert into #table2 ( id, name )

  • SQL Server2019数据库之简单子查询的具有方法

    子查询可以完成 SQL 查询中比较复杂的情况,本章主要介绍一些子查询的简单用法. 一.简单子查询 1.简单子查询 子查询是 SELECT 语句内的另外一条 SELECT 语句.通常,语句内可以出现表达式的地方都可以使用子查询.另外,子查询可以从任何表中提取数据,只要对该表有适当的访问权限即可.因此,通过在一个查询内或者在另一个子查询内嵌套子查询,可以从两个或多个表中组合信息而不必编写复杂的整个组合表,然后再过滤掉多余的或不相关的联合行的JOIN语句. 子查询的语法与普通的 SELECT 查询的语

  • SQL Server子查询的深入理解

    当由where子句指定的搜索条件指向另一张表时,就需要使用子查询或嵌套查询. 1 子查询 子查询是一个嵌套在select.insert.update或delete语句或其他子查询中的查询.任何允许使用表达式的地方都可以使用子查询. 1.1语法规则: 子查询的select查询总使用圆括号括起来不能包括compute或for browse子句如果同时指定top子句,则可能只包括order by子句子查询最多嵌套32层,个别查询可能会不支持32层嵌套任何可以使用表达式的地方都可以使用子查询,主要它返回

  • SQL Server高级内容之子查询和表链接概述及使用

    1.子查询概念 (1)就是在查询的where子句中的判断依据是另一个查询的结果,如此就构成了一个外部的查询和一个内部的查询,这个内部的查询就是自查询. (2)自查询的分类 1)独立子查询 ->独立单值(标量)子查询(=) 复制代码 代码如下: Select testID,stuID,testBase,testBeyond,testPro from Score where stuID=( select stuID from Student where stuName='Kencery' ) ->

  • MySQL数据库之union,limit和子查询详解

    目录 1.where中的子查询 2.from子句后的子查询 3.union 4.limit查询 5.分页 1.where中的子查询 示例数据参见此文章 案例:查询比最低工资高的员工姓名和薪资 子查询,先查询子查询括号里的,再向上级进行查询 mysql> select ename,sal from emp where sal -> > -> (select min(sal) from emp); +--------+---------+ | ename | sal | +------

  • 行转列之SQL SERVER PIVOT与用法详解

    在数据库操作中,有些时候我们遇到需要实现"行转列"的需求,例如一下的表为某店铺的一周收入情况表: WEEK_INCOME(WEEK VARCHAR(10),INCOME DECIMAL) 我们先插入一些模拟数据: INSERT INTO WEEK_INCOME SELECT '星期一',1000 UNION ALL SELECT '星期二',2000 UNION ALL SELECT '星期三',3000 UNION ALL SELECT '星期四',4000 UNION ALL SE

  • SQL Server之JSON 函数详解

    SQL Server 2005开始支持XML数据类型,提供原生的XML数据类型.XML索引及各种管理或输出XML格式的函数.随着JSON的流行,SQL Server2016开始支持JSON数据类型,不仅可以直接输出JSON格式的结果集,还能读取JSON格式的数据. 1 概述 本篇文件将结合MSND简要分析Sqlserver中JSON函数,主要包括ISJSON,JSON_VALUE,JSON_MODIFY,JSON_QUERY. 2 具体内容 2.1 JSON 函数 使用本节中页面中描述的功能来验

  • SQL Server 2000安全配置详解

    SQL server2000数据库应用非常广泛,一旦出现安全问题,造成的损失往往难以估量!应提前预防,防患于未然.这里,我们主要谈论有关SQL Server2000数据库的安全配置以及一些相关的安全和使用上的问题. 在进行SQL Server 2000数据库的安全配置之前,首先你必须对操作系统进行安全配置,保证你的操作系统处于安全状态.然后对你要使用的操作数据库软件(程序)进行必要的安全审核,比如对ASP.PHP等脚本,这是很多基于数据库的WEB应用常出现的安全隐患,对于脚本主要是一个过滤问题,

  • Python基于Pymssql模块实现连接SQL Server数据库的方法详解

    本文实例讲述了Python基于Pymssql模块实现连接SQL Server数据库的方法.分享给大家供大家参考,具体如下: 数据库版本:SQL Server 2012. 按照Python版本来选择下载pymssql模块,这样才能连接上sql server. 我安装的python版本是3.5 ,64位的,所以下载的pymssql模块是:pymssql-2.1.3-cp35-cp35m-win_amd64.whl 我把文件下载后放到E盘,安装pymssql模块: C:\Users\Administr

  • SQL Server 索引和视图详解

    目录 索引 1. 什么是索引 2. 索引分类 聚集索引 非聚集索引 其他类型索引 3. 创建索引 4. 适合的创建索引的列 5. 不适合创建索引的列 视图 1. 什么是视图 2. 创建视图准则 3. 创建视图 4. 修改视图 5. 加密视图 总结 索引 1. 什么是索引 索引就是数据表中数据和相应的存储位置的列表,利用索引可以提高在表或视图中的查找数据的速度. 2. 索引分类 数据库中索引主要分为两类:聚集索引和非聚集索引.SQL Server 2005还提供了唯一索引.索引视图.全文索引.xm

  • SQL Server中的数据类型详解

    目录 哪些对象需要数据类型 一. 整数数据类型 1.bit 2.tinyint 3.smallint 4.int (integer) 5.bigint 二. 浮点数据类型 1.real: 近似数值型 2.float[(n)]:近似数值型 3.decimal[p [s] ] 4.numeric[p [s] ] 5.smallMoney货币型 6.money货币型 三.字符数据类型 1.char[(n)] 2.nchar[(n)] 3.varchar[(n| max )] 4.nvarchar[(n

  • SQL Server比较常见数据类型详解

    在SQL Server 中每个变量.参数.表达式等都有数据类型.系统提供的数据类型分为几大类,如表4-2 所示. 其中,BIGINT. SQL_VARIANT 和TABLE 是SQL Server 2000 中新增加的3 种数据类型.下面分类讲述各种数据类型. 一. 整数数据类型 整数数据类型是最常用的数据类型之一. 1.INT (INTEGER) INT (或INTEGER)数据类型存储从-2的31次方 (-2 ,147 ,483 ,648) 到2的31次方-1 (2 ,147 ,483,64

  • SQL SERVER 日期格式转换详解

    SQL SERVER 2000用sql语句如何获得当前系统时间就是用GETDATE(); Sql中的getDate()2008年01月08日 星期二 14:59Sql Server 中一个非常强大的日期格式化函数 复制代码 代码如下: Select CONVERT(varchar(100), GETDATE(), 0);-- 05 16 2008 10:57AMSelect CONVERT(varchar(100), GETDATE(), 1);-- 05/16/08Select CONVERT

  • SQL Server:触发器实例详解

    1. 概述 触发器是一种特殊的存储过程,它不能被显式地调用,而是在往表中插入记录﹑更新记录或者删除记录时被自动地激活. 所以触发器可以用来实现对表实施复杂的完整性约束. 2. 触发器的分类 SQL Server2000提供了两种触发器:"Instead of" 和"After" 触发器. 一个表或视图的每一个修改动作(Insert.Update和Delete)都可以有一个"Instead of" 触发器,一个表的每个修改动作都可以有多个"

随机推荐