选择语句以在列表中获得树状结构

时间:2014-04-07 07:24:18

标签: sql oracle

我有一个包含以下条目的sql表:

ID, Name, ParentID   
1,  A,  null
2,  B,  null
3,  C,  1
4,  D,  null
5,  E,  1

我希望获得按名称排序的列表,但是sub应该在父

之后
Expected result: A, C, E, B, D

如何使用SQL查询解决此问题? parentID上的groupby不能解决问题,因为我得到(C,E),(A,B,D)

3 个答案:

答案 0 :(得分:0)

我曾经能够通过在C#中进行查询来实现类似的功能: (它至少可以在SQL服务器上运行)

select t.animalid as animalid,
 t.sireid as S,
 t.damid as D, 

 t1.damid as SD,
 t2.sireid as DS,
 t2.damid as DD,
 t3.sireid as SSS,
 t3.damid as SSD
 from PedigreeData t

 left join PedigreeData t1 on t1.animalidt.sireid
 left join PedigreeData t2 on t2.animalidt.damid
 left join PedigreeData t3 on t1.sireidt3.animalid;

答案 1 :(得分:0)

如果您只有一个级别的父/子,您只需使用:

SELECT  NVL(ParentID, ID) AS ParentID,  
        LISTAGG(Name, ', ') WITHIN GROUP (ORDER BY ID) AS Members
FROM    T
GROUP BY NVL(ParentID, ID);

这给出了:

PARENTID    MEMBERS
---------------------
1           A, C, E
2           B
4           D

<强> Example on SQL Fiddle

否则,您将需要使用递归来获取每个成员的基本ID(即,如果您有第6个实体,其父ID = 5):

WITH CTE AS
(   SELECT  CONNECT_BY_ROOT ID AS ID, 
            Name, 
            LEVEL As LVL,
            MAX(LEVEL) OVER(PARTITION BY ID) AS MaxLevel
    FROM    T
    CONNECT BY PRIOR ID = ParentID
)
SELECT  ID, 
        LISTAGG(Name, ', ') WITHIN GROUP (ORDER BY ID) AS Members
FROM    CTE
WHERE   LVL = MaxLevel
GROUP BY ID;

给出了:

ID  MEMBERS
1   A, C, E, F
2   B
4   D

使用第一个查询结果将是:

ID  MEMBERS
1   A, C, E
2   B
4   D
5   F

<强> Example on SQL Fiddle

答案 2 :(得分:0)

对于Oracle,此变体有效:

select 
  listagg(Name, ',') 
    within group (order by rn)         -- Collect values as arranged
                                       -- in previous query 
from (
  select
    rownum rn,                         -- Collect order of rows 
    Name
  from t
  start with ParentID is null
  connect by prior ID = ParentID       -- Get hierarchy by ParentID
  order siblings by Name               -- Arrange nodes on each level by Name   
)

SQLFiddle