【问题标题】:How to do WHERE-CLAUSE in hierarchical query in Oracle如何在 Oracle 的分层查询中执行 WHERE-CLAUSE
【发布时间】:2012-07-14 22:33:43
【问题描述】:

在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.

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

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

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

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

谢谢。

谢谢。

【问题讨论】:

  • 使用 JOIN 语法进行连接以及条件 is 的 WHERE 子句可以回答您的问题。这正是这些构造的用途。它使您的陈述的意图更加清晰。

标签: sql oracle hierarchical-data hierarchical-query


【解决方案1】:

您不应使用隐式连接,而应使用显式 JOINs。

一旦你这样做了,你就可以区分“真实”的 where 条件和 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 无论如何都为空,则连接不会产生任何结果。

【讨论】:

  • 但是我想知道分层查询中WHERE子句拆分的规则。是不是oracle的版权?
  • @user1527818:对不起,你失去了我。
【解决方案2】:

如果需要显式拆分,可以使用括号和内联视图来实现。

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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多