1.1.1 子查询合并
子查询合并(Subquery
Coalescing)的目的是将等价的半连接以及反连接子查询组合到同一个查询块中。应用这种自11.2版本起可用的基于启发式的查询变换,其主要目的是减少表访问的数量,从而减少连接的数量。
下面的例子来自subquery_coalescing.sql脚本,演示了这种查询转换是如何工作的。注意,两个相互关联的子查询处理相同的数据,只是限制条件有所区别:
SELECT *
FROM t1
WHERE EXISTS(SELECT 1 FROM t2 WHERE t2.id =
t1.id AND t2.n>10)
OR
EXISTS(SELECT 1 FROM t2 WHERE t2.id = t1.id AND t2.n<100);
子查询合并组合两个子查询并产生以下查询:
SELECT *
FROM t1
WHERE EXISTS(SELECT 1 FROM t2 WHERE t2.id =
t1.id AND (t2.n >10 OR t2.n<100));
通过子查询展开,可以将查询进一步转化成以下形式。注意,正如在上一节中所解释的,下面的查询使用一个特殊的运算符 (s=)来实现半连接。这个运算符仅可以在SQL引擎内部使用,并非那种可以在书写SQL语句时指定的语法的一部分:
SELECT t1.*
FROM t1,t2
WHERE t1.id s= t2.id AND (t2.n > 10 OR
t2.n<100);
1.1.1 使用窗口函数移除子查询
使用窗口函数移除子查询(Subquery
Removal Using Window Function)的目的是使用窗口函数替换包含聚合函数的子查询。这是一种基于启发式的查询转换,可以在一个查询块包含所有出现在一个子查询中的表和谓词时应用。
下面的例子基于subquery_removal.sql脚本,演示了这种查询转换是如何工作的。注意,在顶层查询和子查询中都引用了t2表:
SELECT t1.id, t1.n, t2.id, t2.n
FROM t1, t2
WHERE t1.id = t2.t1_id
AND t2.n = (SELECT max(n) FROM t2 WHERE
t2.t1_id = t1.id);
查询转换移除子查询,并产生接下来的查询。注意CASE表达式是如何用来生成某种标志的。这种标志用来识别那些满足在原始查询中由子查询指定的限制条件的记录:
SELECT t1.id, t1.n, t2.id, t2.n
FROM (SELECT t1.id as t1_id,t1.n as t1_n,
t2.id as t2_id, t2.n as t2_n,
case t2.n
when max(t2.n) over (partition by t2.t1_id) then 1
end as max
from t2,t1
WHERE t1.id = t2.t1_id) vw_wif
WHERE max is not null);




