1

connect by ステートメントを使用して再帰データを並べ替えるクエリがあります。私が抱えている問題は、1 対多または多対 1 の関係がときどきあり、対処方法がわからないことです。

  SELECT  *  
FROM (SELECT * FROM bdTable WHERE parentek = t_parKey)
START WITH source is null
CONNECT BY PRIOR target = source 

だから説明する。ソース列とターゲット列があります。約 99% の場合、これらは単一の一意の ID です。残念ながら、残りの 1% の時間では、列の 1 つで ID がグループ化されています。この表は、フローチャート タイプのツールをフラットに表現したものであるため、多くの出力を持つ分割と決定、および多くの入力を持つ可能性のあるマージがあります。

テーブルのデータをロードする際にこれに対処するために、listagg 関数を使用して一意の ID を連結します。したがって、「1254143,2356334,6346436,3454363,3462354,442356」のようなターゲット値になります。

したがって、私の connect by ステートメントが実行されると、これらのシナリオの 1 つになるまでは完全に機能し、その時点で停止します (これは当然のことです)。
何らかの方法で IN または INSTR を使用して機能させることができると思いましたが、まだ運がなく、オンラインで何も見つかりません。

任意の助けをいただければ幸いです.....

4

1 に答える 1

0

各列にリストされている一連の値の交差に基づいて、いくつかのロジックを使用して結合targetしたい場合、最も信頼できる方法は、文字列をコレクションに分割し、前の行からのコレクションと現在の行からのコレクションを操作することですsource木を作ること。

Oracle で区切られた文字列からコレクションを構築する手法は多数ありますが、そのうちの 1 つがこの別の質問への回答に示されています

必要なコレクション タイプを作成します。

create or replace type TIdList as table of varchar2(100);

あなたの場合の内部選択は次のようになります。

SELECT
  t.*,
  (
    cast(multiset( -- Convert set of values into collection
      select  -- Build list of values from separated string
          substr(
            source,
            decode( level, 1, 1, instr(source,',',1,level-1)+1 ),
            decode( instr(source,',',1,level), 0, length(source)+1, instr(source,',',1,level) )
              -
              decode( level, 1, 1, instr(source,',',1,level-1)+1 )
          ) code
      from dual
      start with source is not null
      connect by instr(source,',',1,level-1) > 0

    ) as TIdList )
  )                          source_id_list,
  (
    cast(multiset( -- Convert set of values into collection
      select  -- Build list of values from separated string
          substr(
            target,
            decode( level, 1, 1, instr(target,',',1,level-1)+1 ),
            decode( instr(target,',',1,level), 0, length(target)+1, instr(target,',',1,level) )
              -
              decode( level, 1, 1, instr(target,',',1,level-1)+1 )
          ) code
      from dual
      start with target is not null
      connect by instr(target,',',1,level-1) > 0
    ) as TIdList )
  )                          target_id_list
FROM bdTable t
WHERE t.parentek = t_parKey

sourceどの列 (またはtarget) に区切りリストが含まれているのかわからないため、それぞれの列を含めます。

コレクションを構築した後、マルチセット演算子と利用可能なテスト関数を使用して、ターゲットとソースを一致させることができます。例えば

with inner_query as (
  SELECT
    t.*,
    (
      cast(multiset( -- Convert set of values into collection
        select  -- Build list of values from separated string
            substr(
              source,
              decode( level, 1, 1, instr(source,',',1,level-1)+1 ),
              decode( instr(source,',',1,level), 0, length(source)+1, instr(source,',',1,level) )
                -
                decode( level, 1, 1, instr(source,',',1,level-1)+1 )
            ) code
        from dual
        start with source is not null
        connect by instr(source,',',1,level-1) > 0

      ) as TIdList )
    )                          source_id_list,
    (
      cast(multiset( -- Convert set of values into collection
        select  -- Build list of values from separated string
            substr(
              target,
              decode( level, 1, 1, instr(target,',',1,level-1)+1 ),
              decode( instr(target,',',1,level), 0, length(target)+1, instr(target,',',1,level) )
                -
                decode( level, 1, 1, instr(target,',',1,level-1)+1 )
            ) code
        from dual
        start with target is not null
        connect by instr(target,',',1,level-1) > 0
      ) as TIdList )
    )                          target_id_list
  FROM bdTable t
  WHERE t.parentek = t_parKey
)
select 
  level       lvl,
  tree_list.*
from
  inner_query tree_list
start with  
  source is null
connect by 
  nvl(cardinality(prior target_id_list MULTISET INTERSECT source_id_list),0) > 0

値のリストを含めることができる列が 1 つだけの場合は、MEMBER OF構文が役立ちます。

于 2013-07-02T17:57:15.427 に答える