2012-07-16 97 views
4

在Oracle分层查询中,应在Oracle文档中的Connect-By操作符说明之后评估WHERE-CLAUSE。如何在Oracle中的分层查询中执行WHERE-CLAUSE

但也有复杂的情况:如果WHERE-CLAUSE包含JOIN样式限定条件,如oracle所述,Join-Style限定条件应在Connect-By操作符之前进行评估,而另一个无参考样式仅限于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和(B2 = 1或F1 = b2和B1 = 1或F2 = B1 + 1)和F1不为空, 已成为两个部分:

之一:滤波器(( “B2”= 1 OR “B1”= 1)AND “F1” IS NOT NULL) - >评估后连接-由

的其他:过滤器(“F1”=“B2”或“F2”=“B1”+1)和访问(“F1”=“B1”) - >在连接前评估为JOIN-ON

那么,谁可以解释如何区分WHERE子句中的条件以及如何在连接之前或之后应用WHERE子句中的两个部分?

谢谢。

谢谢。

+0

使用JOIN语法加入和条件***的WHERE子句是***您的问题的答案。这正是这些结构的用途。它使你的发言意图更清晰。 – 2012-07-17 07:27:47

回答

1

您不应该使用隐式联接,而应该使用显式的JOIN

一旦你这样做,你可以区分条件与连接条件的“真实”。

我不清楚(这是使用隐式连接语法的结果)您想要用作连接条件的什么以及作为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是空反正不会产生任何结果。

+0

但我想知道在分层查询中拆分WHERE子句的规则。它是否是oracle的版权? – user1527818 2012-07-16 08:49:47

+0

@ user1527818:对不起,你失去了我。 – 2012-07-16 09:02:44

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;