我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SQLServer的子查询详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SQLServer的子查询详解

一、子查询基础知识

子查询是嵌套在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 [Name]
FROM Production.Product
WHERE ListPrice =
    (SELECT ListPrice
     FROM Production.Product
     WHERE [Name] = 'Chainring Bolts' );
GO


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子查询内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SQLServer的子查询详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SQLServer的子查询详解

子查询是嵌套在SELECT、INSERT、UPDATE、DELETE语句中或另一个子查询中的查询。可以在允许表达式的任何位置使用子查询,本文介绍了SQLServer的子查询,需要的朋友可以参考阅读
2023-05-15

SQL Server的子查询详解

目录一、子查询基础知识二、子查询规则三、限定子查询中的列名四、子查询的多层嵌套五、相关子查询六、子查询类型总结一、子查询基础知识子查询是嵌套在SELECT、INSERT、UPDATE、DELETE语句中或另一个子查询中的查询。可以在允许表
2023-04-12

MySql中子查询内查询示例详解

西北望乡何处是,东南见月几回圆。 月亮又慢悠悠的挂上了天空,趁着睡前梦呓,我就带领各位可爱的读者们探索MySql最后的子查询部分。 说明:有些查询结果出来结果截图与题目要求不一样会出现多余的字段是为了方便展示结果的可读性。实际操作的读者可以
2022-05-25

实例详解mysql子查询

子查询分类 按返回结果集分类 子查询按返回结果集的不同分为4种:表子查询,行子查询,列子查询和标量子查询。 表子查询:返回的结果集是一个行的集合,N行N列(N>=1)。表子查询经常用于父查询的FROM子句中。 行子查询:返回的结果集是一个列
2022-05-19

MySQL:子查询(全面详解)

MySQL:子查询 前言一、需求分析与问题解决1、实际问题2、子查询的基本使用3、子查询的分类 二、单行子查询1、单行比较操作符2、代码示例3、HAVING 中的子查询4、CASE中的子查询5、子查询中的空值问题6、非法使用子查
2023-08-16

MySQL总结(十一)子查询-详解

子查询1. 什么是子查询-- 需求:查询开发部中有哪些员工select * from emp;-- 通过两条语句查询select id from dept where name="开发部" ;select * from emp where dept_id =
MySQL总结(十一)子查询-详解
2020-06-24

Mysql查询优化之IN子查询优化方法详解

这篇文章主要给大家介绍了关于Mysql查询优化之IN子查询优化的相关资料,需要的朋友可以参考下
2023-02-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录