利用 SQL 语言提供的方便语法,可以将语句表达为嵌套查询。但是,由于 SQL Anywhere 可以更为有效地利用子查询的 WHERE 子句中的高选择性条件,因此将嵌套查询重写为连接通常会提高执行和优化的效率。一般情况下,会始终对 FROM 子句中最多包含一个表的相关子查询(用于 ANY、ALL 和 EXISTS 谓语中)执行取消子查询嵌套。如果根据查询语义可以确定子查询最多返回一行,则不相关子查询或在 FROM 子句中有多个表的子查询将被展平。
对于外部块中的每个行,以下示例中的子查询最多可以匹配一行。由于该子查询最多可以匹配一行,SQL Anywhere 将发现可以将其转换为内连接。
SELECT s.* FROM SalesOrderItems s WHERE EXISTS ( SELECT * FROM Products p WHERE s.ProductID = p.ID AND p.ID = 300 AND p.Quantity > 20); |
转换之后,这一相同语句将使用连接语法在内部表达:
SELECT s.* FROM Products p JOIN SalesOrderItems s ON p.ID = s.ProductID WHERE p.ID = 300 AND p.Quantity > 20; |
p<Products> JNL s<FK_ProductID_ID>
同样,以下查询在子查询中包含一个连接性 EXISTS 谓语。该子查询可以匹配多个行。
SELECT p.* FROM Products p WHERE EXISTS ( SELECT * FROM SalesOrderItems s WHERE s.ProductID = p.ID AND s.ID = 2001); |
SQL Anywhere 在 SELECT 列表中使用 DISTINCT,将该查询转换为内连接。
SELECT DISTINCT p.* FROM Products p JOIN SalesOrderItems s ON p.ID = s.ProductID WHERE s.ID = 2001; |
Work[ DistH[ s<FK_ID_ID> JNL p<Products> ] ]
对于外部块中的每一行,如果该子查询最多可以匹配一行,则 SQL Anywhere 也可以在比较中排除子查询。下面的查询中就存在这种情况。
SELECT * FROM Products p WHERE p.ID = ( SELECT s.ProductID FROM SalesOrderItems s WHERE s.ID = 2001 AND s.LineID = 1 ); |
SQL Anywhere 以如下方式重写该查询:
SELECT p.* FROM Products p, SalesOrderItems s WHERE p.ID = s.ProductID AND s.ID = 2001 AND s.LineID = 1; |
s<SalesOrderItems> JNL p<Products>
在执行取消子查询嵌套的重写优化时,会将 DUMMY 表视为一个特殊的表。即使子查询不相关,也始终会在形式为 SELECT expression FROM DUMMY
的子查询上执行子查询展平。
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |