2014-10-17 133 views
1

我有這樣的Oracle 11g查詢:自參照表的SQL查詢來行

SELECT RPAD(' ', 2 * (T.ID_LEVEL - 1)) || T.IDE IDE, T.ID_LEVEL, T.CODE, T.FK_IDE 
FROM TEST_DYNAMIC T 
START WITH T.FK_IDE = 0 
CONNECT BY NOCYCLE PRIOR T.IDE = T.FK_IDE 
ORDER BY T.IDE,T.FK_IDE; 

返回此數據:

IDE |IDE_LEVEL |CODE |FK_IDE | 
-----|-----------|------|--------| 
1 |   1|A01 |  0| 
2 |   2|A01 |  1| 
    3 |   3|A01 |  2| 
    4|   4|A01 |  3| 
5 |   2|A02 |  1| 
6 |   2|A03 |  1| 
    7 |   3|A01 |  6| 
8 |   1|A02 |  0| 

正如你所看到的,是從自我refrencing表得到的數據,其中IDE_LEVEL列是包含此值(1,2,3,4)作爲PK的主表的外鍵,而IDE列是來自TEST_DYNAMIC表的自動增量PK。

有一種方法以該結果轉換爲這一個?:

IDE |CODE_LEVEL1 |CODE_LEVEL2 |CODE_LEVEL3 |CODE_LEVEL4 | 
-----|-------------|-------------|-------------|-------------| 
1 |A01   |A01   |A01   |A01   | 
1 |A01   |A02   |NULL   |NULL   | 
1 |A01   |A03   |A01   |NULL   | 
8 |A02   |NULL   |NULL   |NULL   | 

在預期的結果如上所述,IDE列被示出對應於在FK_COLUMN三個ocurrences關鍵1三次,和第一個結果集中鍵8的一次(這一個沒有子元素,因此必須顯示在結果集中)。

任何幫助將不勝感激。

+0

查詢和數據結果是否正確? – itsols 2014-10-17 00:19:50

+0

是的,他們是。 FK_IDE列用於父驗證。當爲0時,則其他root是來自另一個不是root的父節點的子節點。 – iperezmel78 2014-10-17 00:37:44

+0

所以你想旋轉你當前的結果集?你正在使用哪個版本?這些是使用'case'的版本高達10g的例子,使用'pivot'向上的版本高達11g。 – 2014-10-17 07:19:31

回答

0

起初我沒有得到這個問題。你不需要PIVOT,你需要在不同的列中顯示每個分支的路徑。無論如何,根據級別的數量,你可能需要一些動態的sql

with test_dynamic as (
select 1 ide, 1 id_level, 'A01' code, 0 fk_ide from dual 
union all select 2, 2, 'A01', 1 from dual 
union all select 3, 3, 'A01', 2 from dual 
union all select 4, 4, 'A01', 3 from dual 
union all select 5, 2, 'A02', 1 from dual 
union all select 6, 2, 'A03', 1 from dual 
union all select 7, 3, 'A01', 6 from dual 
union all select 8, 1, 'A02', 0 from dual 
), 
tree as (
select code, level lvl, sys_connect_by_path(code, '/') path, connect_by_isleaf lf, connect_by_root(ide) root_ide 
from test_dynamic t 
start with t.fk_ide = 0 
connect by nocycle prior t.ide = t.fk_ide 
) 
select root_ide, path, 
     regexp_substr(path, '[^/]+', 1, 1), 
     regexp_substr(path, '[^/]+', 1, 2), 
     regexp_substr(path, '[^/]+', 1, 3), 
     regexp_substr(path, '[^/]+', 1, 4) 
from tree where lf = 1; 
+0

令人驚歎! 這就是解決方案! 我不知道你在查詢中寫的connect_by函數,但現在我知道了。呵呵呵。動態sql也是需要的,但這對我來說是一項工作。 我欠你一個人。 非常感謝你!!問候。 – iperezmel78 2014-10-17 17:50:41

0

如果級別的數量是動態的,那麼無論如何您都需要使用動態SQL來創建具有動態列的查詢。

至少有2種方法如何創建這樣一個查詢:

1)甲骨文與PIVOT(因爲11克我想)

with test_dynamic as (
select 1 ide, 1 id_level, 'A01' code, 0 fk_ide from dual 
union all select 2, 2, 'A01', 1 from dual 
union all select 3, 3, 'A01', 2 from dual 
union all select 4, 4, 'A01', 3 from dual 
union all select 5, 2, 'A02', 1 from dual 
union all select 6, 2, 'A03', 1 from dual 
union all select 7, 3, 'A01', 6 from dual 
union all select 8, 1, 'A02', 0 from dual 
), 
tree as (
select level lvl, t.ide, t.code 
from test_dynamic t 
start with t.fk_ide = 0 
connect by nocycle prior t.ide = t.fk_ide 
), 
pivot_data as (
select * from tree pivot xml (max(code) lvl_code for lvl in (select distinct lvl from tree)) 
) 
select ide, 
     extractvalue(lvl_xml,'/PivotSet/item[1]/column[2]') code_level1, 
     extractvalue(lvl_xml,'/PivotSet/item[2]/column[2]') code_level2, 
     extractvalue(lvl_xml,'/PivotSet/item[3]/column[2]') code_level3, 
     extractvalue(lvl_xml,'/PivotSet/item[4]/column[2]') code_level4 
from pivot_data t order by 1; 

(人們說,extractValue一起有可能成爲過時的和推薦使用XMLTABLE,但我從來沒有與這個工作)

2)的Oracle DECODE

with test_dynamic as (
select 1 ide, 1 id_level, 'A01' code, 0 fk_ide from dual 
union all select 2, 2, 'A01', 1 from dual 
union all select 3, 3, 'A01', 2 from dual 
union all select 4, 4, 'A01', 3 from dual 
union all select 5, 2, 'A02', 1 from dual 
union all select 6, 2, 'A03', 1 from dual 
union all select 7, 3, 'A01', 6 from dual 
union all select 8, 1, 'A02', 0 from dual 
), 
tree as (
select level lvl, t.ide, t.code 
from test_dynamic t 
start with t.fk_ide = 0 
connect by nocycle prior t.ide = t.fk_ide 
) 
select ide, 
     max(decode(lvl, 1, code, null)) code_level1, 
     max(decode(lvl, 2, code, null)) code_level2, 
     max(decode(lvl, 3, code, null)) code_level3, 
     max(decode(lvl, 4, code, null)) code_level4 
from tree group by ide order by 1; 
+0

嗨Multisync。 完全同意您推薦的動態sql部分。 我測試了發送的查詢,但都返回8行,只需要三個,它代表可以在值爲1的FK_IDE列中看到的根父級的每個孩子。無論如何,感謝您的答覆。問候。 – iperezmel78 2014-10-17 15:30:08

+0

@ iperezmel78我不明白 - 爲什麼ide = 5,6,7的行必須忽略? – Multisync 2014-10-17 16:30:02

+0

@ iperezmel78,好吧,我想我知道了 - 在結果數據透視表中,每行代表根的分支。目前尚不清楚,說實話。 – Multisync 2014-10-17 16:45:44