SQL子查询
在本教程中,我们将学习SQL子查询,它是嵌套在另一个查询中以形成复杂查询的常规查询。
SQL子查询介绍
子查询是嵌套在另一个查询(如SELECT、UPDATE或DELETE语句)中的常规SELECT语句。
下图说明了子查询的概念:
子查询也称为内部选择或内部查询,而包含子查询的查询称为外部选择或外部查询。
在上图中,子查询返回一个由三行组成的结果集。
SELECT DISTINCT reportsto FROM employees
将此结果集提取到外部查询的IN运算符。外部查询等同于:
SELECT employeeid, firstname, lastname FROM employees WHERE employeeid IN (5 , 3, null);
它返回employees表中的所有经理。
在本例中,子查询的结果由外部查询使用。数据库引擎执行整个查询两次,一次用于子查询,一次用于外部查询。
子查询也可以嵌套在另一个子查询中。嵌套级别的数量取决于特定数据库产品的实现。例如,Microsoft SQL Server最多支持32个级嵌套。
SQL子查询示例
在以下示例中,我们将使用以下表:
customers – 存储客户主数据。
products – 存储产品主数据。
orders_test – 存储订单头数据,包括进行采购的客户。
orderdetails – 存储订单行项目数据。
子查询可以返回一行或多行。
当子查询返回一行时,可以在外部查询中使用比较运算符(如=、>、<、>=、<=和<>)将值与子查询返回的值进行比较。
例如,以下查询使用不等于(<>)运算符选择与客户id BSBEV位于同一城市的所有客户:
SELECT customerid, companyname, city FROM customers WHERE customerid <> 'BSBEV' AND city = (SELECT city FROM customers WHERE customerid = 'BSBEV')
首先,子查询返回客户BSBEV所在的城市,即London。然后,使用London
向外部查询提供数据,以查找位于伦敦市的所有客户。
使用IN和NOT IN的SQL子查询示例
如果子查询返回包含多行的结果集,则可以在外部查询中使用In或NOT In运算符来检查值是否在子查询返回的结果集中。
例如,以下查询美国客户的所有订单,子查询选择美国客户的所有ID,外部查询使用这组ID选择订单:
SELECT orderid, customerid, shipname FROM orders_test WHERE customerid IN ( SELECT customerid FROM customers WHERE country = 'USA');
您还可以使用NOT-IN运算符查询美国以外的所有订单,如下所示:
SELECT orderid, customerid, shipname FROM orders_test WHERE customerid NOT IN ( SELECT customerid FROM customerS WHERE country = 'USA')
在UPDATE 语句中使用SQL子查询
子查询不仅嵌套在SELECT语句中,还可以嵌套在其他语句(如UPDATE和DELETE语句)中。
例如,下面的语句将supplierid为15的供应商提供的产品单价提高5%:
UPDATE products SET unitprice = unitprice * 1.05 WHERE productid IN ( SELECT productid FROM suppliers WHERE supplierid = 15);
子查询选择supplierid为15的供应商提供的产品的所有id。然后,将id集提取到UDPATE语句中以更新单价。
SQL子查询作为表达式的示例
子查询可用于替换SQL语句中的表达式。
例如,下面的查询返回所有饮料产品的价格、产品的平均价格以及单价和平均价格之间的差异。
SELECT productid, productname, (SELECT AVG(unitprice) FROM products) AS 'average price', (unitprice - ( SELECT AVG(unitprice) FROM products)) AS diff FROM products WHERE categoryid = 1
带有EXISTS和NOT EXISTS运算符的SQL子查询
子查询与EXISTS和NOT EXISTS运算符组合时,可用于测试行是否存在。