参考

2012-04-30 8 views
0

私はこのようになり、データがあります:私は(この場合09/10 10000 A1234で)ルート複合キーに対してクエリを実行されるだろうとなる参考

KEY1 KEY2  KEY3 LKEY1 LKEY2  LKEY3 FLAG 
====== ========= ====== ====== ========= ====== ===== 
09/10 10000  A1234 09/10 AU00A1234 1 
09/10 10000  A1234 09/10 AU000456 A1234 1 
09/10 10000  A1234 09/10 AX000001 A1234 1 
09/10 AX000001 A1234 09/10 AE000010 A1234 0 
09/10 AX000001 A1234 09/10 AE000020 A1234 0 
09/10 AX000001 A1234 09/10 AE000030 A1234 0 
09/10 10000  A1234 09/10 AX000002 A1234 0 
09/10 AX000002 A1234 09/10 AE000040 A1234 0 
09/10 10000  A1234 09/10 AU000789 A1234 0 

これは、階層的なデータです。 FLAGフィールドはLKEYxキーで識別される「オブジェクト」を参照します。ネストのレベルはいくつでもかまいません。 (KEY1KEY3フィールドは限り階層が保存されているように、上記の例のように、不変である必要はないことに注意してください。)私が取得したい何

がリーフノードで、しかし葉の親であればKEY2の長さはLKEY2と同じか、または2番目の文字としてXが含まれている場合は、直接の親を返します。この場合、我々はまた、このような何か...オプションとして、レコードをマークする必要がありそう:

KEY1 KEY2  KEY3 OPTION FLAG 
====== ========= ====== ======= ===== 
09/10 AU00A1234 0  1 
09/10 AU000456 A1234 0  1 
09/10 AX000001 A1234 1  1 
09/10 AX000002 A1234 1  0 
09/10 AU000789 A1234 0  0 

を私はこれを行うクエリを書かれているが、それはかなりありません。さらに、オプションのレコードを区別するために、すべてのリーフノードがツリーの下の同じレベルにあると仮定します。しかしながら、これは必ずしも真実ではない。次のように私のクエリは次のとおりです。

with queryKeys as (
    select '09/10' key1, 
     '10000' key2, 
     'A1234' key3, 
    from dual 
), 
subTree as (
    select  tree.key1, 
      tree.key2, 
      tree.key3, 

      tree.lkey1, 
      tree.lkey2, 
      tree.lkey3, 

      tree.flag, 

      connect_by_isleaf isLeaf, 
      level thisLevel 

    from  tree, 
      queryKeys 

    start with tree.key1 = queryKeys.key1 
    and  tree.key2 = queryKeys.key2 
    and  tree.key3 = queryKeys.key3 

    connect by tree.key1 = prior tree.lkey1 
    and  tree.key2 = prior tree.lkey2 
    and  tree.key3 = prior tree.lkey3 
), 
maxTree as (
    select max(thisLevel) maxLevel 
    from subTree 
) 
select lkey1 key1, 
     lkey2 key2, 
     lkey3 key3, 
     1 - isLeaf option, 
     flag 

from subTree, 
     maxTree 
where (isLeaf = 1 or thisLevel = maxLevel - 1) 
and (length(key2) != length(lkey2) or substr(lkey2, 2, 1) != 'X'); 

queryKeysの理由は、それが大きなクエリ内の他の場所で使用しているためで、一つのレコードよりも多くを含めることができます。 maxTreeの部分は、その一般的な奇妙さを超えて、問題です!

この投稿のタイトルは、親のFLAGフィールドを参照できる場合はより多くの場合、このクエリを多く作成することができるためです。私はJOINというアプローチを試しました - ツリーを関連するキーで自分自身に結びつけました - 私が間違っていない限り、ツリーを繰り返してツリーを見つけ出す必要がある再帰的な問題が発生します正しい親キー(KEYxフィールドとLKEYxフィールドの両方がレコードの完全な複合キーを定義しているため)。

(PSそれが違いを行う場合は、Oracle 10gリリース2を使用した。)

答えて

3

ちょうど使用:

PRIOR FLAG 

それは正確に何をしたいあなたを与えるだろう - 親行のフラグフィールドを。

subTree as (   
select  tree.key1,    
     tree.key2,    
     tree.key3,    
     tree.lkey1,    
     tree.lkey2,    
     tree.lkey3,    
     tree.flag,    
     PRIOR TREE.FLAG PRIOR_FLAG 
     connect_by_isleaf isLeaf,    
     level thisLevel    

from  tree,    
     queryKeys 
(...) 
+0

美しい!ありがとうございました :) – Xophmeister

1

私はあなたのポストは質問、「どのように私は、階層問合せで親行のFLAG属性を参照するかに帰着すると仮定しましたか? "

私が思いついたSQLが正しいかどうかわかりません。そうでない場合はお詫び申し上げます。しかし、一般的に私のアプローチは次のとおりです。

階層内の各レベルで、すべてのキー(SYS_CONNECT_BY_PATH)を組み合わせてストリングしました。次に、SUBSTR,INSTRおよびLEVELを使用して、I SUBSTRが、親レベルのキーに相当する量を出す。最後に、PARENT_FLAGの定義では、このSUBSTRと一致するキーの行のFLAGを選択します。

セットアップ:

CREATE TABLE tree (
    key1  VARCHAR2(5) 
, key2  VARCHAR2(10) 
, key3  VARCHAR2(5) 
, lkey1  VARCHAR2(5) 
, lkey2  VARCHAR2(10) 
, lkey3  VARCHAR2(5) 
, flag  VARCHAR2(1) 
); 
INSERT INTO tree VALUES ('09/10','10000','A1234','09/10','AU000123','A1234','1'); 
INSERT INTO tree VALUES ('09/10','10000','A1234','09/10','AU000456','A1234','1'); 
INSERT INTO tree VALUES ('09/10','10000','A1234','09/10','AX000001','A1234','1'); 
INSERT INTO tree VALUES ('09/10','AX000001','A1234','09/10','AE000010','A1234','0'); 
INSERT INTO tree VALUES ('09/10','AX000001','A1234','09/10','AE000020','A1234','0'); 
INSERT INTO tree VALUES ('09/10','AX000001','A1234','09/10','AE000030','A1234','0'); 
INSERT INTO tree VALUES ('09/10','10000','A1234','09/10','AX000002','A1234','0'); 
INSERT INTO tree VALUES ('09/10','AX000002','A1234','09/10','AE000040','A1234','0'); 
INSERT INTO tree VALUES ('09/10','10000','A1234','09/10','AU000789','A1234','0'); 

問合せ:

COL flag   FOR A4 
COL same_length FOR A11 
COL has_x_2nd  FOR A9 
COL full_key_path FOR A50 
COL parent_key FOR A30 
COL parent_flag FOR A11 
WITH querykeys AS (
    SELECT '09/10' key1 
    ,  '10000' key2 
    ,  'A1234' key3 
    FROM DUAL 
) 
, subtree1 AS (
    SELECT  tree.key1 
    ,   tree.key2 
    ,   tree.key3 
    ,   tree.lkey1 
    ,   tree.lkey2 
    ,   tree.lkey3 
    ,   tree.flag 
    ,   CONNECT_BY_ISLEAF isleaf 
    ,   LEVEL thislevel 
    ,   DECODE(LENGTH(tree.key2) 
      ,  LENGTH(tree.lkey2), '1' 
      ,  '0') same_length 
    ,   DECODE(UPPER(SUBSTR(tree.key2,2,1)) 
      ,  'X', '1' 
      ,  '0') has_x_2nd 
    ,   SYS_CONNECT_BY_PATH(tree.key1 || '|' || tree.key2 || '|' || tree.key3,'\') 
      || '\' 
      || tree.lkey1 || '|' || tree.lkey2 || '|' || tree.lkey3 || '\' full_key_path 
    FROM  tree 
    ,   querykeys 
    START WITH tree.key1 = querykeys.key1 
    AND  tree.key2 = querykeys.key2 
    AND  tree.key3 = querykeys.key3 
    CONNECT BY tree.key1 = PRIOR tree.lkey1 
    AND  tree.key2 = PRIOR tree.lkey2 
    AND  tree.key3 = PRIOR tree.lkey3 
) 
, subtree2 AS (
    SELECT st1.key1 
    ,  st1.key2 
    ,  st1.key3 
    ,  st1.lkey1 
    ,  st1.lkey2 
    ,  st1.lkey3 
    ,  st1.flag 
    ,  st1.isleaf 
    ,  st1.thislevel 
    ,  st1.same_length 
    ,  st1.has_x_2nd 
    ,  st1.full_key_path 
    ,  SUBSTR(st1.full_key_path 
      ,  INSTR(st1.full_key_path,'\',1,st1.thislevel) + 1 
      ,  INSTR(st1.full_key_path,'\',1,st1.thislevel + 1) 
        - INSTR(st1.full_key_path,'\',1,st1.thislevel) - 1) parent_key 
    FROM subtree1 st1 
) 
SELECT st2.key1 
,  st2.key2 
,  st2.key3 
,  st2.lkey1 
,  st2.lkey2 
,  st2.lkey3 
,  st2.flag 
,  st2.isleaf 
,  st2.thislevel 
,  st2.same_length 
,  st2.has_x_2nd 
,  (SELECT t_prime.flag 
     FROM tree t_prime 
     WHERE t_prime.key1 = SUBSTR(st2.parent_key 
           ,  1 
           ,  INSTR(st2.parent_key,'|',1,1) - 1) 
     AND t_prime.key2 = SUBSTR(st2.parent_key 
           ,  INSTR(st2.parent_key,'|',1,1) + 1 
           ,  INSTR(st2.parent_key,'|',1,2) 
            - INSTR(st2.parent_key,'|',1,1) - 1) 
     AND t_prime.key3 = SUBSTR(st2.parent_key 
           ,  INSTR(st2.parent_key,'|',1,2) + 1) 
     -- Following assumes all rows with parent keys have same flag value. 
     -- Avoids ORA-01427: single-row subquery returns more than one row. 
     AND ROWNUM = 1) parent_flag 
FROM subtree2 st2 
; 

結果:私は、私は、完全にあなたのデータモデルをgrokked 100%わからないんだけど、言ったように

KEY1 KEY2  KEY3 LKEY1 LKEY2  LKEY3 FLAG  ISLEAF THISLEVEL SAME_LENGTH HAS_X_2ND PARENT_FLAG 
----- ---------- ----- ----- ---------- ----- ---- ---------- ---------- ----------- --------- ----------- 
09/10 10000  A1234 09/10 AU00A1234 1    1   1 0   0   1 
09/10 10000  A1234 09/10 AU000456 A1234 1    1   1 0   0   1 
09/10 10000  A1234 09/10 AU000789 A1234 0    1   1 0   0   1 
09/10 10000  A1234 09/10 AX000001 A1234 1    0   1 0   0   1 
09/10 AX000001 A1234 09/10 AE000010 A1234 0    1   2 1   1   0 
09/10 AX000001 A1234 09/10 AE000020 A1234 0    1   2 1   1   0 
09/10 AX000001 A1234 09/10 AE000030 A1234 0    1   2 1   1   0 
09/10 10000  A1234 09/10 AX000002 A1234 0    0   1 0   0   1 
09/10 AX000002 A1234 09/10 AE000040 A1234 0    1   2 1   1   0 

9 rows selected. 

SQL> 

が、あなたが私のアプローチに従うことができることを願っています。

+0

私はあなたの努力のためにパスを解析する上での単純さのために@ arturroの回答を選択しましたが、+1しました。ありがとう:) – Xophmeister