【问题标题】:How to retrieve All childrens using a Select SQL Server query如何使用 Select SQL Server 查询检索所有子项
【发布时间】:2015-01-10 08:04:58
【问题描述】:

我有一个如下所示的输入表:

ID       NAME       PARENT_ID
------------------------------------
1        ABC          0
2        DEF          1
3        XYZ          1
4        PQR          2
5        GHI          0
6        JKL          5
7        MNO          6
8        STU          6

我希望以逗号分隔的字符串形式输出如下:

ABC, ABC -> DEF, ABC -> XYZ, ABC -> DEF -> PQR
GHI, GHI -> JKL, GHI -> JKL -> MNO, GHI -> JKL -> STU

我尝试了 CTE 和 Cross Apply,但没有成功。有人可以帮我实现这一目标吗?

最好的问候

【问题讨论】:

    标签: sql sql-server-2008 recursion


    【解决方案1】:

    你可以做这样的事情。 如果您愿意,可以检查您的 SQL,我还为您创建了插入查询,只需检查即可。

    检查输出的数据

    create table tbl
    (
     ID int,
     NAME  varchar(20),
     PARENT_ID int
     )  
     insert into
     tbl
     values
     (1 ,'ABC', 0),
    
    (2, 'DEF', 1),
    
    (3 ,'XYZ', 1),
    
    (4 ,'PQR', 2)
    select * from tbl
    

    查询

    select table2.NAME as ChildName,table1.NAME as ParentName from tbl as table1 
    inner join tbl table2 on table1.ID = table2.PARENT_ID 
    

    【讨论】:

      【解决方案2】:

      如果您想检索分层列表:

      with cte_1(ID, PARENT_ID, LABEL)
      as (
        select ID, PARENT_ID, cast(NAME as varchar(512))
        from a_table
        where PARENT_ID = 0
      union all
        select a.ID, a.PARENT_ID,  cast(b.LABEL + ' --> ' +a.NAME as varchar(512))
        from a_table a
        join cte_1 b on a.PARENT_ID = b.ID
      )
      select LABEL from cte_1
      order by LABEL
      

      这给了你:

      'ABC'
      'ABC --> DEF'
      'ABC --> DEF --> PQR'
      'ABC --> XYZ'
      'GHI'
      'GHI --> JKL'
      'GHI --> JKL --> MNO'
      'GHI --> JKL --> STU'
      

      如果您还想将列表连接到单个字符串中,您可以使用更多 CTE:

      -- recursively build the hierarchical list
      with cte_1(ID, PARENT_ID, LABEL)
      as (
        select ID, PARENT_ID, cast(NAME as varchar(512))
        from a_table
        where PARENT_ID = 0
      union all
        select a.ID, a.PARENT_ID,  cast(b.LABEL + ' --> ' +a.NAME as varchar(512))
        from a_table a
        join cte_1 b on a.PARENT_ID = b.ID
      ),
      -- order them
      cte_2 (NR, LABEL)
      as (
        select row_number() over (order by LABEL) as NR,
        LABEL  
        from cte_1 
      ), 
      -- recursive concatenation
      cte_3 (NR, LABEL) as (
        select NR, cast(LABEL as varchar(1024))
        from cte_2 where NR = 1
      union all
        select a.NR, cast(b.LABEL + ', ' + a.LABEL as varchar(1024))
        from cte_2 a
        join cte_3 b on a.NR = b.NR + 1
      )
      -- get the result
      select top 1 LABEL
      from cte_3
      order by len(LABEL) desc
      

      结果是:

      'ABC, ABC --> DEF, ABC --> DEF --> PQR, ABC --> XYZ, GHI, GHI --> JKL, GHI --> JKL --> MNO, GHI --> JKL --> STU'
      

      【讨论】:

        【解决方案3】:

        基于@bwt 的回答

        您可以执行以下操作

        declare @table table(Id int identity(1,1),
                             Name varchar(10),
                             Parent_Id int)
        insert into @table(Name,Parent_Id) values('ABC',0)
        insert into @table(Name,Parent_Id) values('DEF',1)
        insert into @table(Name,Parent_Id) values('XYZ',1)
        insert into @table(Name,Parent_Id) values('PQR',2)
        insert into @table(Name,Parent_Id) values('GHI',0)
        insert into @table(Name,Parent_Id) values('JKL',5)
        insert into @table(Name,Parent_Id) values('MNO',6)
        insert into @table(Name,Parent_Id) values('STU',6);
        
        with c(ID, PARENT_ID, LABEL)
        as (
          select ID, PARENT_ID, cast(NAME as varchar(512))
          from @table
          where PARENT_ID = 0
        union all
          select a.ID, a.PARENT_ID,  cast(b.LABEL + ' --> ' +a.NAME as varchar(512))
          from @table a
          join c b on a.PARENT_ID = b.ID
        )
        

        --使用的东西

        select replace(STUFF((Select ',' +LABEL
        from c t1
        FOR XML PATH('')),1,1,''),'>','>')
        

        这里有一个工作的DEMO

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-11-01
          • 1970-01-01
          • 2021-09-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-22
          • 2021-01-18
          相关资源
          最近更新 更多