2017-01-11 3 views
1

のOracle Database 12cのEnterprise Editionのリリース12.1.0.2.0オラクルに接続することでは、私は、私はちょうど何かが欠けてる期待

にあまりにも多くの行を生成するようだが、私は「によって接続」なしでこのクエリを実行する場合、I 2行を取得します。私が "レベルで接続< = 4"を追加すると、それらの2つの行のそれぞれを4回得ることが期待されます。実際の結果は異なります。

ここで何が起こっているのか分かりますか?私は各行を4回だけ繰り返すソリューションを探しているわけではありません - 私は既にそれを持っています。私は何が起こっているのか、そしてなぜそれが理解できるのか探しています。

with alpha as (
     select 1 as id 
      from dual 
    ), 
    beta as (
     select 1 as alpha_id, 
       1 as beta_no 
      from dual 
     union all 
     select 1 as alpha_id, 
       2 as beta_no 
      from dual 
    ) 
select a.id, 
     b.beta_no, 
     level as the_level 
    from alpha a 
     inner join beta b 
      on b.alpha_id = a.id 
    connect by level <= 4 
    order by a.id, 
     b.beta_no, 
     level 
; 
ID BETA_NO THE_LEVEL 

 1   1   1 
    1   1   2 
    1   1   2 
    1   1   3 
    1   1   3 
    1   1   3 
    1   1   3 
    1   1   4 
    1   1   4 
    1   1   4 
    1   1   4 
    1   1   4 
    1   1   4 
    1   1   4 
    1   1   4 
    1   2   1 
    1   2   2 
    1   2   2 
    1   2   3 
    1   2   3 
    1   2   3 
    1   2   3 
    1   2   4 
    1   2   4 
    1   2   4 
    1   2   4 
    1   2   4 
    1   2   4 
    1   2   4 
    1   2   4 

30行がmathguyする

感謝を選択しました。彼が以下の答えで提供した第二のリンクは、私が探していたものとまったく同じものでした。具体的には:

1 with t as (select 1 as id from dual union all 
    2    select 2 from dual) 
    3 -- 
    4 select id, level 
    5  ,prior id 
    6  ,sys_connect_by_path(id,'=>') as cpath 
    7 from t 
    8* connect by level <= 3 
SQL>/

     ID  LEVEL PRIORID CPATH 
---------- ---------- ---------- -------------------------------------------------- 
     1   1   =>1 
     1   2   1 =>1=>1 
     1   3   1 =>1=>1=>1 
     2   3   1 =>1=>1=>2 
     2   2   1 =>1=>2 
     1   3   2 =>1=>2=>1 
     2   3   2 =>1=>2=>2 
     2   1   =>2 
     1   2   2 =>2=>1 
     1   3   1 =>2=>1=>1 
     2   3   1 =>2=>1=>2 
     2   2   2 =>2=>2 
     1   3   2 =>2=>2=>1 
     2   3   2 =>2=>2=>2 

14 rows selected. 

この例ではわかりましたが、私は簡単に言葉で言い表せません。

答えて

2

"level < = 4"以外の条件がない場合、元の表、ビューなどのすべての行(この場合は結合から)はレベル2で2行、次にレベル3でさらに4行「Connect by」は本質的に継承の継承です.PRIOR演算子を使用して条件がない場合は、十字結合を実行しています。

"および前a.id = a.id"を追加することをお勧めします。これにより、Oracleはサイクルに不満を持ちます(OracleはPRIORの対象となる列に同じ値を表示するとサイクルに達すると判断するため)。これは、通常、「以前のsys_guid()がnullではない」という第3の条件を追加することで解決されます。

編集、使用する際に必要とされないNOCYCLE、元の回答からなる基準アプローチ「前SYS_GUID()がnullでない」)

これは、OTN上で最近議論されている:https://community.oracle.com/thread/3999985

ここで説明

同じ質問:https://community.oracle.com/thread/2526535

+1

@Boneist - 右!私は明確にするために編集します。ありがとう! – mathguy

+0

ありがとうmathguyとBoneist。 私が言ったように、私は修正を探していません、私はそれを引き起こす原因を理解しようとしています。私はパスで接続して遊んで、私がそれを理解することができるかどうかを見てみましょう... –

+0

@MattKnowles - 私はあなたの質問への修正としてそれを提供しませんでした - 私は説明の一部としてそれを提供しましたあなたが見たもののリンクをたどってそこからリンクすれば、「特定の問題を解決するためにどのように使用されているか」ではなく、「これがどのように機能するか」に関する議論があることがわかります。あなたがやっているように、自分で演奏することも、確かに多くの助けになります。がんばろう! – mathguy

0

Mathguyの答えを説明するために、あなたはあなたのCONNECT BY句のうちのいくつかの述語が不足している:

with alpha as (
     select 1 as id 
      from dual 
    ), 
    beta as (
     select 1 as alpha_id, 
       1 as beta_no 
      from dual 
     union all 
     select 1 as alpha_id, 
       2 as beta_no 
      from dual 
    ) 
select a.id, 
     b.beta_no, 
     level as the_level 
from alpha a 
     inner join beta b 
     on b.alpha_id = a.id 
connect by level <= 4 
      AND PRIOR a.id = a.id 
      AND PRIOR b.beta_no = b.beta_no 
      AND PRIOR sys_guid() IS NOT NULL 
order by a.id, 
     b.beta_no, 
     LEVEL; 

     ID BETA_NO THE_LEVEL 
---------- ---------- ---------- 
     1   1   1 
     1   1   2 
     1   1   3 
     1   1   4 
     1   2   1 
     1   2   2 
     1   2   3 
     1   2   4 

代替句で再帰を使用するために、次のようになります。

with alpha as (
     select 1 as id 
      from dual 
    ), 
    beta as (
     select 1 as alpha_id, 
       1 as beta_no 
      from dual 
     union all 
     select 1 as alpha_id, 
       2 as beta_no 
      from dual 
    ), 
    multiply (id, beta_no, rn) AS (SELECT a.id, 
              b.beta_no, 
              1 rn 
            FROM alpha a 
              INNER JOIN beta b 
              ON a.id = b.alpha_id 
            UNION ALL 
            SELECT ID, 
              beta_no, 
              rn + 1 
            FROM multiply 
            WHERE rn + 1 <= 4) 
SELECT ID, 
     beta_no, 
     rn AS the_level 
FROM multiply 
order by id, 
     beta_no, 
     rn; 

     ID BETA_NO THE_LEVEL 
---------- ---------- ---------- 
     1   1   1 
     1   1   2 
     1   1   3 
     1   1   4 
     1   2   1 
     1   2   2 
     1   2   3 
     1   2   4 
関連する問題