5

在 Oracle 分层查询中,应在 oracle 文档中的 Connect-By 运算符说明之后评估 WHERE-CLAUSE。

但是有一些复杂的情况:如果 WHERE-CLAUSE 包含 JOIN 样式的限定,如 oracle 所说,应在 Connect-By 运算符之前评估 Join-Style 限定,而另一个仅引用一个关系的非连接样式将是在 Connect-By 运算符之后进行评估。

那么问题来了:如何将 WHERE-CLAUSE 中的限定条件分为两部分,一是在 Connect-By 算子之前求值,二是在 Connect-By 算子之后求值。

example:
SQL> desc bar
Name                                      Null?    Type
----------------------------------------- -------- -----------------
B1                                                 NUMBER(38)
B2                                                 NUMBER(38)

SQL> desc foo;
Name                                      Null?    Type
----------------------------------------- -------- -----------------
F1                                                 NUMBER(38)
F2                                                 NUMBER(38)
SQL> set pagesize 3000
SQL> set linesize 3000
SQL> explain plan for select * from foo, bar where
 2  **f1=b1 and (b2 = 1 or f1=b2 and b1=1 or f2=b1+1) and f1 is not null**
 3  connect by level < 10;

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------
Plan hash value: 2657287368

--------------------------------------------------------------------------------------
| Id  | Operation                     | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |      |     1 |    52 |     5  (20)| 00:00:01 |
|*  1 |  FILTER                       |      |       |       |            |          |
|*  2 |   CONNECT BY WITHOUT FILTERING|      |       |       |            |          |
|*  3 |    HASH JOIN                  |      |     1 |    52 |     5  (20)| 00:00:01 |
|   4 |     TABLE ACCESS FULL         | FOO  |     1 |    26 |     2   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL         | BAR  |     1 |    26 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - **filter(("B2"=1 OR "B1"=1) AND "F1" IS NOT NULL)**
   2 - filter(LEVEL<10)
   3 - **access("F1"="B1")**
       **filter("F1"="B2" OR "F2"="B1"+1)**

Note
-----
   - dynamic sampling used for this statement

24 rows selected.

所以,如上图所示,WHERE中的条件,f1=b1 and (b2 = 1 or f1=b2 and b1=1 or f2=b1+1) and f1 is not null,变成了两部分:

一:filter(("B2"=1 OR "B1"=1) AND "F1" IS NOT NULL) --> 连接后评估

另一个:filter("F1"="B2" OR "F2"="B1"+1) 和 access("F1"="B1") --> 在连接前评估为 JOIN-ON

那么,谁能解释一下如何区分 WHERE 子句中的条件,以及如何从 WHERE 子句中形成这两部分在 connect-by 之前或之后应用?

谢谢。

谢谢。

4

2 回答 2

1

如果您需要明确拆分它,您可以使用括号和内联视图来实现。

select *
from (select * 
      from foo, bar 
      where f1=b1 and (b2 = 1 or f1=b2 and b1=1 or f2=b1+1) and f1 is not null)
connect by level < 10;
于 2012-07-17T06:56:09.127 回答
1

您不应该使用隐式连接,JOIN而是使用显式连接。

一旦你这样做了,你就可以将“真实”的 where 条件与连接条件区分开来。

我不清楚(这是使用隐式连接语法的结果)您究竟想使用什么作为连接条件以及使用什么作为 where 条件。

将您的查询重写为如下内容:

from foo
   join bar on foo.f1 = bar.b1
where bar.b2 = 1 or ....
  and f1 is not null
connect by level < 10;

该条件f1 is not null似乎是不必要的(即使在您的初始查询中),因为如果 f1 无论如何都为空,则连接不会产生任何结果。

于 2012-07-16T08:45:44.517 回答