Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (中文) » SQL Anywhere 服务器 - SQL 的用法 » 查询和修改数据 » 使用子查询 » 优化程序自动将子查询转换为连接

 

跟在 ANY、ALL 或 SOME 之后的子查询

跟在关键字 ALL、ANY 或 SOME 之后的子查询称为定量比较。如果这些子查询满足以下条件,则优化程序会将其转换为连接:

  • 主查询不包含 GROUP BY 子句,并且不是集合查询,或子查询只返回一个值。

  • 子查询不包含 GROUP BY 子句。

  • 子查询不包含关键字 DISTINCT。

  • 子查询不是 UNION 查询。

  • 子查询不是集合查询。

  • 不得对合取式 'expression comparison-operator { ANY | SOME } ( subquery-expression )' 取非。

  • 必须对合取式 'expression comparison-operator ALL ( subquery-expression )' 取非。

其中的前 4 个条件相对易于理解。

示例

"Clarke 女士和 Suresh 女士何时下的订单,并且是向哪些销售代表下的订单" 这一请求可按以下子查询形式进行处理:

SELECT OrderDate, SalesRepresentative
FROM SalesOrders
WHERE CustomerID = ANY (
   SELECT ID
   FROM Customers
   WHERE Surname = 'Clarke' OR GivenName = 'Suresh' );

上述子查询也可以使用连接形式表示

SELECT OrderDate, SalesRepresentative
FROM SalesOrders, Customers
WHERE CustomerID=Customers.ID AND 
  ( Surname = 'Clarke' OR GivenName = 'Suresh' );

不过,"Clarke 女士和 Suresh 女士以及同样是客户的任何雇员何时下的订单?" 这一请求将以联合查询形式表示,并且无法转换为连接:

SELECT OrderDate, SalesRepresentative
FROM SalesOrders
WHERE CustomerID = ANY (
   SELECT ID
   FROM Customers
   WHERE Surname = 'Clarke' OR GivenName = 'Suresh'
   UNION
   SELECT EmployeeID
   FROM Employees );

类似地,"查找在所有产品第一个发运日期后未发运的那些订单的订单 ID 和客户 ID" 这一请求将表示为集合查询,因此无法转换为连接:

SELECT ID, CustomerID
FROM SalesOrders
WHERE NOT OrderDate > ALL (
   SELECT FIRST ( ShipDate )
   FROM SalesOrderItems 
   ORDER BY ShipDate );
对具有 ANY 和 ALL 运算符的子查询取非

第五个条件更令人费解一些。采用以下形式的查询将被转换为连接:

SELECT select-list 
FROM table 
WHERE NOT expression comparison-operator ALL ( subquery-expression ) 
SELECT select-list
FROM table
WHERE expression comparison-operator ANY ( subquery-expression )

不过,以下查询不会被转换为连接:

SELECT select-list
FROM table
WHERE expression comparison-operator ALL ( subquery-expression )
SELECT select-list
FROM table
WHERE NOT expression comparison-operator ANY ( subquery-expression )

前两个查询是等同的,后两个查询也是如此。请回想一下,ANY 运算符类似于 OR 运算符,但其参数数量是可变的;类似地,ALL 运算符也与 AND 运算符类似。例如,以下两个表达式是等同的:

NOT ( ( X > A ) AND ( X > B ) )
( X <= A ) OR ( X <= B )

以下两个表达式也是等同的:

WHERE NOT OrderDate > ALL (
   SELECT FIRST ( ShipDate )
   FROM SalesOrderItems
   ORDER BY ShipDate )
WHERE OrderDate <= ANY (
   SELECT FIRST ( ShipDate )
   FROM SalesOrderItems
   ORDER BY ShipDate )
对 ANY 和 ALL 表达式取非

一般来说,以下表达式是等同的:

NOT column-name operator ANY ( subquery-expression )
column-name inverse-operator ALL ( subquery-expression )

以下表达式通常也是等同的:

NOT column-name operator ALL ( subquery-expression )
column-name inverse-operator ANY ( subquery-expression )

其中 inverse-operator 是通过对 operator 取非而获得的,如下表所示:

运算符 反向运算符
= <>
< =>
> =<
=< >
=> <
<> =