5

Oracle 階層クエリでは、Oracle ドキュメントの Connect-By 演算子の後に WHERE-CLAUSE を評価する必要があります。

しかし、複雑な状況があります。オラクルが言うように、WHERE-CLAUSE に JOIN スタイルの修飾が含まれている場合、Connect-By 演算子の前に Join-Style 修飾を評価する必要があり、1 つの関係のみを参照する他の非結合スタイルが評価されます。 Connect-By 演算子の後に評価されます。

問題は、WHERE-CLAUSE の条件を 2 つの部分に区別する方法です。1 つは Connect-By 演算子の前に評価され、もう 1 つは 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 の条件は、次の 2 つの部分になります。

one: filter(("B2"=1 OR "B1"=1) AND "F1" IS NOT NULL) --> 接続後に評価

その他: filter("F1"="B2" OR "F2"="B1"+1) and access("F1"="B1") --> connect-by の前に JOIN-ON として評価

では、WHERE 句の条件を区別する方法と、connect-by の前後に適用される WHERE 句から 2 つの部分を形成する方法を誰が説明できますか?

ありがとう。

ありがとう。

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。代わりに明示的な s を使用してください。

これを行うと、「実際の」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 が null の場合、結合によって結果が得られないため、(最初のクエリでも)条件は不要のようです。

于 2012-07-16T08:45:44.517 に答える