企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
>[danger] ## [子查询]- 介绍子查询概念并向您展示如何使用各种子查询类型来查询数据。 #### 1\. SQL Server子查询简介 子查询是嵌套在另一个语句(如:SELECT,INSERT,UPDATE或DELETE中的查询。 现在来看下面的例子,考虑示例数据库中的`orders` 和 `customers`表,它们的结构和关系如下: ![](https://www.yiibai.com/uploads/article/2019/02/21/105721_78873.png) 以下语句显示如何在`SELECT`语句的WHERE子句中使用子查询来查找位于纽约(`New York`)的客户的销售订单: ~~~sql SELECT order_id, order_date, customer_id FROM sales.orders WHERE customer_id IN ( SELECT customer_id FROM sales.customers WHERE city = 'New York' ) ORDER BY order_date DESC; ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/03/2e/032e9fa2cc3c261df0912e535dfa558f_1386x710.png) 在此示例中,以下语句是子查询: ~~~sql SELECT customer_id FROM sales.customers WHERE city = 'New York' ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/cf/d7/cfd78bd644a0cd5dab983512df7cbc4f_1386x711.png) 请注意,必须始终将子查询的`SELECT`查询括在括号`()`中。 子查询也称为内部查询或内部选择,而包含子查询的语句称为外部选择或外部查询: ![SQL Server子查询](https://www.yiibai.com/uploads/article/2019/02/21/110434_49562.png) SQL Server执行上面的整个查询示例,如下所示: 首先,它执行子查询以获取城市为`New Year`的客户的客户标识号列表。 ~~~sql SELECT customer_id FROM sales.customers WHERE city = 'New York' ~~~ 其次,SQL Server替换[IN](http://www.yiibai.com/sqlserver/sql-server-in.html "IN")运算符中子查询返回的客户标识号,并执行外部查询以获取最终结果集。 如您所见,通过使用子查询,可以将两个步骤组合在一起。 子查询消除了选择客户标识号并将其插入外部查询的需要。 此外,只要客户数据发生变化,查询本身就会自动进行调整。 #### 2\. 嵌套子查询 子查询可以嵌套在另一个子查询中。 SQL Server最多支持`32`个嵌套级别。 请考虑以下示例: ~~~sql SELECT product_name, list_price FROM production.products WHERE list_price > ( SELECT AVG (list_price) FROM production.products WHERE brand_id IN ( SELECT brand_id FROM production.brands WHERE brand_name = '上海永久' OR brand_name = '凤凰' ) ) ORDER BY list_price; ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/f8/b5/f8b5beb916402979c891618ffe5100b4_1391x712.png) 上面语句有些复杂,如果第一眼没有看明白,没有关系,可通过以下步骤一步步地理解。 **首先**,SQL Server执行以下子查询以获取品牌名称为`'上海永久'`和`'凤凰'`的品牌标识号列表: ~~~sql SELECT brand_id FROM production.brands WHERE brand_name = '上海永久' OR brand_name = '凤凰'; ~~~ 执行上面查询语句,得到以下结果: ![](https://www.yiibai.com/uploads/article/2019/02/21/111813_90306.png) **第二步**,SQL Server计算属于这些品牌的所有产品的平均价格。 ~~~sql SELECT AVG (list_price) FROM production.products WHERE brand_id IN (1,2) ~~~ **第三步**,SQL Server查找价格高于`'上海永久'`和`'凤凰'`品牌的所有产品的平均定价的产品。 #### 3\. SQL Server子查询类型 可以在许多地方使用子查询: * 代替表达 * 使用IN或NOT IN * ANY或ALL * 有EXISTS或`NOT EXISTS`语句中。 * 在UPDATE,DELETE或INSERT语句中。 **3.1. SQL Server子查询用于代替表达式** 如果子查询返回单个值,则可以在使用表达式的任何位置使用它。 ~~~sql SELECT order_id, order_date, ( SELECT MAX (list_price) FROM sales.order_items i WHERE i.order_id = o.order_id ) AS max_list_price FROM sales.orders o order by order_date desc; ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/c5/71/c5719c575fb1b6cb927056d847783504_1392x713.png) **3.2. SQL Server子查询与IN运算符** 与`IN`运算符一起使用的子查询返回一组零个或多个值。 子查询返回值后,外部查询将使用它们。 以下查询查找出售的所有山地自行车和公路自行车产品的名称。 ~~~sql SELECT product_id, product_name FROM production.products WHERE category_id IN ( SELECT category_id FROM production.categories WHERE category_name = 'Mountain Bikes' OR category_name = 'Road Bikes' ); ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/f4/0f/f40fa845077f23d15ebe9f2e2f1d68de_640x527.png) 此查询分两步进行评估: * 首先,内部查询返回与名称`Mountain Bikes`和`Road Bikes`相匹配的类别标识号列表。 * 其次,这些值被替换为外部查询,外部查询查找具有类别标识号与列表中的一个值匹配的产品名称。 **3.2. SQL Server子查询与ANY运算符一起使用** 使用`ANY`运算符引入子查询的语法: ~~~sql scalar_expression comparison_operator ANY (subquery) ~~~ 假设子查询返回值为:`v1`,`v2`,`... vn`的列表。 如果比较`scalar_expression`中的一个评估为`TRUE`,则`ANY`运算符返回`TRUE`; 否则,它返回`FALSE`。 例如,以下查询查找价格大于或等于任何产品品牌的平均价格的产品。 ~~~sql SELECT product_name, list_price FROM production.products WHERE list_price >= ANY ( SELECT AVG (list_price) FROM production.products GROUP BY brand_id ) ~~~ 执行上面示例代码,得到以下结果: 子查询与ANY运算符一起使用 对于每个品牌,子查询都会找到平均价格。 外部查询使用这些最大价格并确定哪个单独产品的清单价格大于或等于任何品牌的平均价格。 **SQL Server子查询与ALL运算符一起使用** `ALL`运算符与`ANY`运算符具有相同的语法: ~~~sql scalar_expression comparison_operator ALL (subquery) ~~~ 如果所有比较`scalar_expression`的计算结果为`TRUE`,则`ALL`运算符返回`TRUE`; 否则,它返回`FALSE`。 以下查询查找列表价格大于或等于子查询返回的平均价格的产品: ~~~sql SELECT product_name, list_price FROM production.products WHERE list_price >= ALL ( SELECT AVG (list_price) FROM production.products GROUP BY brand_id ) ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/7f/f1/7ff1b76f7d4dc8c6d4c127f3a536da21_1391x713.png) **3.3. SQL Server子查询与EXISTS或NOT EXISTS一起使用** 以下语句使用EXISTS运算符引入的子查询的语法: ~~~sql WHERE [NOT] EXISTS (subquery) ~~~ 如果子查询返回结果,则`EXISTS`运算符返回`TRUE`; 否则返回`FALSE`。 另一方面,`NOT EXISTS`与`EXISTS`运算符相反。 以下查询查找`2017`年购买产品的客户: ~~~sql SELECT customer_id, first_name, last_name, city FROM sales.customers c WHERE EXISTS ( SELECT customer_id FROM sales.orders o WHERE o.customer_id = c.customer_id AND YEAR (order_date) = 2017 ) ORDER BY first_name, last_name; ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/98/23/98230e5f0d4976f7b2fc2f4d34f284b7_1392x711.png) 如果使用`NOT EXISTS`,可以查找`2017`年未购买任何产品的客户。 ~~~sql SELECT customer_id, first_name, last_name, city FROM sales.customers c WHERE NOT EXISTS ( SELECT customer_id FROM sales.orders o WHERE o.customer_id = c.customer_id AND YEAR (order_date) = 2017 ) ORDER BY first_name, last_name; ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/8c/d1/8cd1b51b9d222e23794caaac6950e644_1389x712.png) >[danger] ## [相关子查询] - 介绍相关子查询概念以及如何使用。 相关子查询是使用外部查询的值的[子查询](http://www.yiibai.com/sqlserver/sql-server-subquery.html "子查询")。 换句话说,它取决于外部查询的值。 由于这种依赖性,相关子查询不能作为简单子查询独立执行。 此外,对外部查询评估的每一行重复执行一次相关子查询。相关子查询也称为**重复子查询**。 请考虑示例数据库中的以下`products`表: ![](https://www.yiibai.com/uploads/article/2019/02/21/185730_30277.png) 以下示例查找价格等于其类别的最高价格的产品。 ~~~sql SELECT product_name, list_price, category_id FROM production.products p1 WHERE list_price IN ( SELECT MAX (p2.list_price) FROM production.products p2 WHERE p2.category_id = p1.category_id GROUP BY p2.category_id ) ORDER BY category_id, product_name; ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/9d/25/9d25d389799ccc5e2eaf60cfbfa1963d_1387x707.png) 在此示例中,对于由外部查询评估的每个产品,子查询查找其类别中所有产品的最高价格。 如果当前产品的价格等于其类别中所有产品的最高价格,则产品将包含在结果集中。 此过程将继续进行下一个产品,依此类推。 >[danger] ## [EXISTS] - 测试子查询返回的行的存在性。 **1\. 带子查询的EXISTS返回NULL示例** 请参阅示例数据库中的`customers`表。 Exists返回NULL示例 以下示例返回`customers`表中的所有行: ~~~sql SELECT customer_id, first_name, last_name FROM sales.customers WHERE EXISTS (SELECT NULL) ORDER BY first_name, last_name; ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/32/46/324608fcec4ee081efa6b1b337fa8d8e_1387x717.png) 在此示例中,子查询返回包含`NULL`的结果集,这也导致`EXISTS`运算符计算为`TRUE`。 **1.2. EXISTS带有相关子查询示例** 考虑以下`customers`和`orders`表,它们的结构如下所示: ![](https://www.yiibai.com/uploads/article/2019/02/21/191511_86408.png) 以下示例查找已下过两个以上订单的所有客户: ~~~sql SELECT customer_id, first_name, last_name FROM sales.customers c WHERE EXISTS ( SELECT COUNT (*) FROM sales.orders o WHERE customer_id = c.customer_id GROUP BY customer_id HAVING COUNT (*) > 2 ) ORDER BY first_name, last_name; ~~~ 执行上面查询语句,得到以下结果: EXISTS带有相关子查询示例 在这个例子中,我们有一个相关的子查询,它返回下过两个以上订单的客户。 如果客户下达的订单数小于或等于`2`,则子查询返回一个空结果集,该结果集导致`EXISTS`运算符计算为`FALSE`。 根据`EXISTS`运算符的结果,客户是否包含在结果集中。 **1.3. EXISTS 与 IN示例** 以下语句使用`IN`运算符查找城市为`San Jose`的客户订单: ~~~sql SELECT * FROM sales.orders WHERE customer_id IN ( SELECT customer_id FROM sales.customers WHERE city = 'San Jose' ) ORDER BY customer_id, order_date; ~~~ 以下语句使用返回相同结果的`EXISTS`运算符: ~~~sql SELECT * FROM sales.orders o WHERE EXISTS ( SELECT customer_id FROM sales.customers c WHERE o.customer_id = c.customer_id AND city = 'San Jose' ) ORDER BY o.customer_id, order_date; ~~~ 执行上面查询语句,得到以下结果: EXISTS 与 IN示例 **1.4. EXISTS与JOIN** `JOIN`子句从另一个表返回行记录,`EXISTS`运算符返回`TRUE`或`FALSE`。 可以使用`EXISTS`运算符来测试子查询是否返回行,并尽快进行短路。 另一方面,使用`JOIN`将结果集与另一个相关表中的列组合来扩展结果集。 >[danger] ## [ANY]- 将值与子查询返回的单列值集进行比较,如果值与集合中的任何值匹配则并返回`TRUE`。 ## SQL Server ANY运算符简介 `ANY`运算符是一个逻辑运算符,它将标量值与子查询返回的单列值集进行比较。 以下是`ANY`运算符的语法: ~~~sql scalar_expression comparison_operator ANY (subquery) ~~~ 在上面语法中, * `scalar_expression` - 是任何有效的表达式。 * `comparison_operator` - 是任何比较运算符。 * `subquery`是一个SELECT语句,它返回单个列的结果集,其数据与标量表达式的数据类型相同。 假设子查询返回值列表`v1,v2,...,vn`。 如果`ANY`比较(`scalar_expression,vi`)返回`TRUE`,则`ANY`运算符返回`TRUE`。 否则它返回`FALSE`。 请注意,`SOME`运算符等效于`ANY`运算符。 ## SQL Server ANY运算符示例 请参阅示例数据库中的以下`products`表,结构如下所示: ![](https://www.yiibai.com/uploads/article/2019/02/21/213633_57820.png) 以下示例查找销售订单中销售数量超过`2`个的产品: ~~~sql SELECT product_name, list_price FROM production.products WHERE product_id = ANY ( SELECT product_id FROM sales.order_items WHERE quantity >= 2 ) ORDER BY product_name; ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/05/31/0531e9ea135a908a7a22e9aff594ef87_1387x708.png) >[danger] ## [ALL]- 将值与子查询返回的单列值集进行比较,如果值与集合中的所有值匹配并返回`TRUE`。 SQL Server `ALL`运算符是一个逻辑运算符,它将标量值与子查询返回的单列值列表进行比较。 以下是`ALL`运算符语法: ~~~sql scalar_expression comparison_operator ALL ( subquery) ~~~ 在上面语法中, * `scalar_expression`是任何有效的表达式。 * `comparison_operator`是任何有效的比较运算符,包括等于(`=`),不等于(`<>`),大于(`>`),大于或等于(`>=`),小于(`<`),小于或等于(`<=`)。 * 括号内的子查询(`subquery`)是一个[SELECT](http://www.yiibai.com/sqlserver/sql-server-select.html "SELECT")语句,它返回单个列的结果。 此外,返回列的数据类型必须与标量表达式的数据类型相同。 如果所有比较对`(scalar_expression,v)`的计算结果为`TRUE`,则`ALL`运算符返回`TRUE`; `v`是单列结果中的值。 如果其中一对`(scalar_expression,v)`返回`FALSE`,则`ALL`运算符返回`FALSE`。 ## SQL Server ALL运算符示例 请考虑[示例数据库](https://www.yiibai.com/sqlserver/sql-server-sample-database.html "示例数据库")中的以下`products`表。 ![](https://www.yiibai.com/uploads/article/2019/02/22/080928_81734.png) 以下查询语句返回每个品牌的产品平均价格: ~~~sql SELECT AVG (list_price) avg_list_price FROM production.products GROUP BY brand_id ORDER BY avg_list_price; ~~~ 执行上面查询语句,得到以下结果: ![](https://img.kancloud.cn/5a/ef/5aefd963f435c7030d11b7056be09cd0_641x530.png) **1\. scalar\_expression > ALL ( subquery )** 如果`scalar_expression`大于子查询返回的最大值,则表达式返回`TRUE`。 例如,以下查询查找价格大于所有品牌产品的平均价格的产品: ~~~sql SELECT product_name, list_price FROM production.products WHERE list_price > ALL ( SELECT AVG (list_price) avg_list_price FROM production.products GROUP BY brand_id ) ORDER BY list_price; ~~~ 执行上面查询语句,得到以下结果: ![大于所有品牌产品的平均价格](https://www.yiibai.com/uploads/article/2019/02/22/081259_29909.png "大于所有品牌产品的平均价格") **2\. scalar\_expression < ALL ( subquery )** 如果标量表达式(`scalar_expression`)小于子查询(`subquery`)返回的最小值,则表达式求值为`TRUE`。 以下示例按品牌查找价格低于平均价格中最低价格的产品: ~~~sql SELECT product_name, list_price FROM production.products WHERE list_price < ALL ( SELECT AVG (list_price) avg_list_price FROM production.products GROUP BY brand_id ) ORDER BY list_price DESC; ~~~ 执行上面查询语句,得到以下结果: ![低于平均价格中最低价格](https://www.yiibai.com/uploads/article/2019/02/22/081512_91044.png "低于平均价格中最低价格") 类似地,也可以使用以下比较运算符之一来使用`ALL`运算符,例如等于(`=`),大于或等于(`>=`),小于或等于(`<=`)和不等于(`<>`)。