2013-08-23 41 views
-1

我有一個源表(T1):如何代碼從Postgres的轉換到Oracle

ID1 | ID2 
---------- 
1 | 2 
1 | 5 
4 | 7 
7 | 8 
9 | 1 

我想將數據轉換成這(T2):

ID1 | ID2 | LABEL 
------------------ 
1 | 2 | 1 
1 | 5 | 1 
4 | 7 | 2 
7 | 8 | 2 
9 | 1 | 1 

我找到了解決爲此在PostgreSQL中:

with 
recursive cte(id1, id2) as (
select id1, id2, 1 as level 
from t 
union all 
select t.id1, cte.id2, cte.level + 1 
from t join 
     cte 
     on t.id2 = cte.id1 
) 
select id1, id2, 
    dense_rank() over (order by grp) as label 
from (select id1, id2, 
     least(min(id2) over (partition by id1), min(id1) over (partition by id2)) as grp, 
     level 
    from cte 
) t 
where level = 1; 

我想將此代碼轉換爲Oracle。我如何將此代碼從Postgres轉換爲Oracle?

+0

沒有,我只發現我應該使用「CONNECT_BY_ROOT()」,因爲在Oracle中遞歸的。鏈接:http://en.wikipedia.org/wiki/Hierarchical_and_recursive_queries_in_SQL – user2693903

+1

請指定您的Oracle版本。這應該與Oracle 11.2一起工作(因爲在那裏引入了遞歸CTE)。您可能需要使用與「LEVEL」不同的內容,因爲這是一個保留字。 –

+0

是的,它是Oracle 11g R2。你可以幫我嗎?它被稱爲「傳遞關係」轉換。 – user2693903

回答

2

Oracle 11.2支持遞歸CTE。但它不符合標準,因爲recursive關鍵字不是必需的(實際上:不能使用)。因此,如果您刪除recursive關鍵字並正確定義CTE列,則以下內容應可用。您還需要使用與LEVEL不同的東西,因爲這是保留字。

with cte (id1, id2, lvl) as (
select id1, id2, 1 as lvl 
from t 
union all 
select t.id1, cte.id2, cte.lvl + 1 
from t 
    join cte on t.id2 = cte.id1 
) 
select id1, 
     id2, 
     dense_rank() over (order by grp) as label 
from (
    select id1, 
     id2, 
     least(min(id2) over (partition by id1), min(id1) over (partition by id2)) as grp, 
     lvl 
    from cte 
) t 
where lvl = 1; 

下面是一個SQLFiddle例如:http://sqlfiddle.com/#!4/deeb2/3

但是我懷疑,原來的查詢是正確的,因爲你沒有在遞歸CTE「起始條件」。該聯盟的第一部分檢索全部行的表格。除非我誤解了查詢的目的,否則應該有條件將其限制爲層次結構的「根」。

遞歸CTE也可以用CONNECT BY查詢替換,你的情況,這將是:

select id1, id2, level as lvl 
from t 
connect by prior id1 = id2; 

你可以結合,與原單查詢:

with cte (id1, id2, lvl) as (
    select id1, id2, level as lvl 
    from t 
    connect by prior id1 = id2 
) 
select id1, 
     id2, 
     dense_rank() over (order by grp) as label 
from (
    select id1, 
     id2, 
     least(min(id2) over (partition by id1), min(id1) over (partition by id2)) as grp, 
     lvl 
from cte 
) t 
where lvl = 1; 

雖然我認爲它應該是一樣的,似乎層次結構是以不同的順序遍歷的。可能是因爲遞歸CTE首先執行深度並且connect by執行了深度優先遞歸(或者相反方向)。對第二個版本

SQLFiddle例如:http://sqlfiddle.com/#!4/deeb2/4

+0

嗨,感謝您的幫助。它的oracle版本不是oracle 11g r2。我如何能找到另一個解決方案。你有什麼想法回合嗎? – user2693903

+0

'connect by'可以與自8.x以來的任何Oracle版本一起使用。但你說**是** 11.2? –

+0

不幸的是,它並沒有在查詢上面工作。我越來越喜歡這個: ID1 | ID2 | LABEL ------------------ 1 | 2 | 1 1 | 5 | 1 4 | 7 | 2 7 | 8 | 3 9 | 1 | 1 – user2693903