2013-08-22 45 views
2

我有一些複雜的分層數據奮鬥的結果。我已成功使用CONNECT BY查詢將行限制爲我想要的子集 - 並且我已使用SYS_CONNECT_BY_PATH將完整樹返回到感興趣的節點。UNPIVOT分隔字符串的幾行

這給了我基本上是這樣的一些行(由分隔「|」):

id path 
------------------- 
1, '|10|11|12|13' 
2, '|10|14|15' 
3, '|16|11|12|13' 
4, '|16|17' 

現在 - 我的挑戰是要解開或UNPIVOT這些值回這樣的結構:

id ord node 
------------- 
1, 1, 10 
1, 2, 11 
1, 3, 12 
1, 4, 13 
2, 1, 10 
2, 2, 14 
2, 3, 15 
3, 1, 16 
3, 2, 11 
3, 3, 12 
3, 4, 13 
4, 1, 16 
4, 2, 17 

我覺得我不能直接使用UNPIVOT作爲正在開發一組固定的列 - 這,這不是。

我與管道功能發揮解開這一點,但坦率地說 - 通過所有這些行功能是一個問題,因爲他們來自另一個查詢。我想知道如果任何人有一種方法來設置回行的SYS_CONNECT_BY_PATH結果也許是一個純粹的SQL解決方案unpivot的價值 - 可能與正則表達式解析...

幫助總是讚賞 - 感謝

+0

你爲什麼將它們連接起來,而不是存儲的值直? – Ben

+0

串聯來自於SYS_CONNECT_BY_PATH的結果 - 在原來的databasae,該值都正確歸到層次 – Randy

回答

4

是, UNPIVOT運營商在這裏不會做大量的工作來幫助您生成所需的輸出。

定期

表達函數計算數字的所有事件,然後使用regexp_substr()定期

表達功能如下提取號碼的方法你可以用戶regexp_count()(11克R1及以上版本)中的一個:

-- sample of data 
SQL> with t1(id1, path1) as(
    2 select 1, '|10|11|12|13' from dual union all 
    3 select 2, '|10|14|15' from dual union all 
    4 select 3, '|16|11|12|13' from dual union all 
    5 select 4, '|16|17' from dual 
    6 ), 
    7 occurrences(ocr) as(-- occurrences 
    8 select level 
    9  from (select max(regexp_count(path1, '[^|]+')) as mx_ocr 
10    from t1 
11   ) t 
12 connect by level <= t.mx_ocr 
13 ) 
14 select id1 
15  , row_number() over(partition by id1 order by id1) as ord 
16  , node 
17 from (select q.id1 
18    , regexp_substr(q.path1, '[^|]+', 1, o.ocr)  as node 
19    from t1 q 
20   cross join occurrences o 
21   ) 
22 where node is not null 
23 order by id1, 2, node 
24 ; 

結果:

 ID1  ORD NODE 
---------- ---------- ------------------------------------------------ 
     1   1 10 
     1   2 11 
     1   3 12 
     1   4 13 
     2   1 10 
     2   2 14 
     2   3 15 
     3   1 11 
     3   2 12 
     3   3 13 
     3   4 16 
     4   1 16 
     4   2 17 

13 rows selected 

作爲另一種方法,從10g版本開始,起來,你可以使用model條款:

SQL> with t1(id1, path1) as(
    2 select 1, '|10|11|12|13' from dual union all 
    3 select 2, '|10|14|15' from dual union all 
    4 select 3, '|16|11|12|13' from dual union all 
    5 select 4, '|16|17' from dual 
    6 ) 
    7 select id1 
    8  , ord 
    9  , node 
10 from t1 
11 model 
12 partition by (rownum as id1) 
13 dimension by (1 as ord) 
14 measures(path1 
15   , cast(null as varchar2(11)) as node 
16   , nvl(regexp_count(path1, '[^|]+'), 0) as ocr) 
17 rules(
18  node[for ord from 1 to ocr[1] increment 1] = 
19   regexp_substr(path1[1], '[^|]+', 1, cv(ord)) 
20 ) 
21 order by id1, ord, node 
22 ; 

結果:

 ID1  ORD NODE 
---------- ---------- ----------- 
     1   1 10 
     1   2 11 
     1   3 12 
     1   4 13 
     2   1 10 
     2   2 14 
     2   3 15 
     3   1 16 
     3   2 11 
     3   3 12 
     3   4 13 
     4   1 16 
     4   2 17 

13 rows selected 

SQLFiddle Demo

+0

尼古拉斯 - 我想我欠你一個啤酒。謝謝。 – Randy

+0

我看到訂單有點關閉...在id = 3節點16顯示最後不是第一..我會玩 – Randy