2014-02-07 52 views
0
CREATE TABLE b(ID   VARCHAR2(50 BYTE), 
        PARENT_ID VARCHAR2(50 BYTE), 
        NAME  NVARCHAR2(200) 
    ); 

https://community.oracle.com/thread/3513540分层表多次合并

上面的链接我解释了一切

+1

请不要用链接描述问题。该链接可能在将来不存在。编辑您的问题并添加相关信息。 –

+0

对不起,我会尽快编辑它 – user3283992

+0

现代的方式是递归CTE http://stackoverflow.com/questions/4659803/recursion-in-oracle – jbaliuka

回答

0

任何原因,你不喜欢answer posted thereSQL Fiddle是否说明了问题的答案,而不是您描述的所需结果?

编辑

一种SQL Fiddle使用该技术Frank Kulashsuggested。这是自2002年以来第一个基于Oracle的查询(在9iAS上)。

SELECT REGEXP_SUBSTR(a.PIDPath, '[^,]+', 1, 1) Header1, 
     REGEXP_SUBSTR(a.IDPath, '[^,]+', 1, 1)  Header2, 
     REGEXP_SUBSTR(a.NamePath, '[^,]+', 1, 1) Header3, 

     REGEXP_SUBSTR(a.PIDPath, '[^,]+', 1, 2) Header4, 
     REGEXP_SUBSTR(a.IDPath, '[^,]+', 1, 2)  Header5, 
     REGEXP_SUBSTR(a.NamePath, '[^,]+', 1, 2) Header6, 

     REGEXP_SUBSTR(a.PIDPath, '[^,]+', 1, 3) Header7, 
     REGEXP_SUBSTR(a.IDPath, '[^,]+', 1, 3)  Header8, 
     REGEXP_SUBSTR(a.NamePath, '[^,]+', 1, 3) Header9, 

     REGEXP_SUBSTR(a.PIDPath, '[^,]+', 1, 4) Header10, 
     REGEXP_SUBSTR(a.IDPath, '[^,]+', 1, 4)  Header11, 
     REGEXP_SUBSTR(a.NamePath, '[^,]+', 1, 4) Header12, 

     REGEXP_SUBSTR(a.PIDPath, '[^,]+', 1, 5) Header13, 
     REGEXP_SUBSTR(a.IDPath, '[^,]+', 1, 5)  Header14, 
     REGEXP_SUBSTR(a.NamePath, '[^,]+', 1, 5) Header15 

     --,REGEXP_SUBSTR(a.PIDPath, '[^,]+', 1, n)  
     --,REGEXP_SUBSTR(a.IDPath, '[^,]+', 1, n)  
     --,REGEXP_SUBSTR(a.NamePath, '[^,]+', 1, n) 

FROM ( SELECT LEVEL        RootLvl, 
       b.ID         RootID, 
       SYS_CONNECT_BY_PATH(b.PARENT_ID, ',') 
        || ','       PIDPath, 
       SYS_CONNECT_BY_PATH(b.ID, ',')   
        || ','       IDPath, 
       SYS_CONNECT_BY_PATH(b.NAME, ',')      
        || ','       NamePath 
     FROM t b 
     START WITH b.PARENT_ID = '1' 
     CONNECT BY NOCYCLE PRIOR b.ID = b.PARENT_ID) a 
ORDER BY a.RootLvl, a.RootID; 

弗兰克Kulash指出:

结果集中的列数必须是硬编码到查询。你今天可以编写一些能够产生30列的东西(也就是说,对于层次结构中的10个层次来说足够了),但是如果你稍后改变了数据以便有11个或更多的层次,那么你的查询就会开始失去结果。

我可能会回来尝试一下PIVOT事情。甲骨文很疯狂。

编辑

但足够管理。静态的PIVOT工程just fine。我不能得到CROSS APPLY像我认为它应该与VALUES(MSSQL风格)一样工作,所以我已经放弃并代之以通过UNION ALL。这个动态SQL可能会有一些工作,所以它实际上可以在不对列进行硬编码的情况下完成你所需要的工作。

; 
WITH c (RID, ID, PARENT_ID, NAME) AS (
    SELECT ROW_NUMBER() OVER (
      ORDER BY PARENT_ID)  RID, 
      ID, PARENT_ID, NAME 
    FROM t 
    UNION ALL 
    SELECT b.RID, a.ID, a.PARENT_ID, a.NAME 
    FROM t a, 
      c b 
    WHERE a.ID = b.PARENT_ID 
) 
SELECT p."'ID_1'"        Header1, 
     p."'PARENT_ID_1'"      Header2, 
     p."'NAME_1'"       Header3, 
     p."'ID_2'"        Header4, 
     p."'PARENT_ID_2'"      Header5, 
     p."'NAME_2'"       Header6, 
     p."'ID_3'"        Header7, 
     p."'PARENT_ID_3'"      Header8, 
     p."'NAME_3'"       Header9, 
     p."'ID_4'"        Header10, 
     p."'PARENT_ID_4'"      Header11, 
     p."'NAME_4'"       Header12, 
     p."'ID_5'"        Header13, 
     p."'PARENT_ID_5'"      Header14, 
     p."'NAME_5'"       Header15 
FROM ( SELECT RID, 
       'ID_' || ROW_NUMBER() OVER (
        PARTITION BY RID 
        ORDER BY ID)    KeyName, 
       ID        KeyValue 
     FROM c 
     UNION ALL 
     SELECT RID, 
       'PARENT_ID_' || ROW_NUMBER() OVER (
        PARTITION BY RID 
        ORDER BY ID)    KeyName, 
       PARENT_ID      KeyValue 
     FROM c 
     UNION ALL 
     SELECT RID, 
       'NAME_' || ROW_NUMBER() OVER (
        PARTITION BY RID 
        ORDER BY ID)    KeyName, 
       CAST(NAME AS VARCHAR2(200)) KeyValue 
     FROM c) s 
PIVOT (MAX(KeyValue) FOR KeyName IN (
      'ID_1', 'PARENT_ID_1', 'NAME_1', 
      'ID_2', 'PARENT_ID_2', 'NAME_2', 
      'ID_3', 'PARENT_ID_3', 'NAME_3', 
      'ID_4', 'PARENT_ID_4', 'NAME_4', 
      'ID_5', 'PARENT_ID_5', 'NAME_5')) p 
ORDER BY p.RID; 
+0

是的,当然如果你仔细看看我说明的表格然后你会发现它们不是一样的输出 – user3283992

+0

没有看到,但还有更多的建议。我猜你想要的更接近我发布的第二件事情 - 可以动态生成以获得更多灵活性。 – Avarkx