use*_*818 5 sql oracle hierarchical-data hierarchical-query
在 Oracle 分层查询中,WHERE-CLAUSE 应该在 oracle 文档中的 Connect-By 运算符之后进行评估。
但是有一些复杂的情况:如果 WHERE-CLAUSE 包含 JOIN-style 限定,正如 oracle 所说,Join-Style 限定应该在 Connect-By 运算符之前进行评估,而另一个仅引用一个关系的 none-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.
Run Code Online (Sandbox Code Playgroud)
所以,如上图所示,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 之前或之后?
谢谢。
谢谢。
小智 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;
Run Code Online (Sandbox Code Playgroud)
该条件f1 is not null
似乎没有必要(即使在您的初始查询中),因为如果 f1 为空,联接将不会产生任何结果。