2017-01-19 77 views
1

我的问题是如何标记在返回的行标识符,会告诉我返回row.id是否有更多的孩子递归获取与识别层次结构孩子haschildren

Sample Data 
id parenId Name parentName 
9 8  nine eight 
8 7  eight seven 
6 8  six eight 
5 8  five eight 
4 8  four eight 
3 8  three eight 
2 1  two one 
1 1  one one 
12 7  tweleve seven 
11 12  eleven twelve 

如果我通过的parentId在此查询7低于它返回我

8 7 eight 
6 8 six 
5 8 five 
4 8 four 
3 8 three 
12 7 tweleve 
11 12 eleven 

但我要的是有更多的孩子被标记,例如8和12有更多的孩子ID

8 7 eight haschidlren 
6 8 six 
5 8 five 
4 8 four 
3 8 three 
12 7 tweleve haschidlren 
11 12 eleven 

WITH name_tree 
    AS (SELECT Id, 
       Parentid, 
       Name, 
       ParentName 
     FROM TableWithHiearchy 
     WHERE Parentid = 7 
     -- this is the starting point you want in your recursion 
     UNION ALL 
     SELECT c.Id, 
       c.Parentid, 
       c.Name, 
       ParentName 
     FROM TableWithHiearchy c 
       JOIN name_tree p 
        ON p.Id = c.ParentId -- this is the recursion 
        AND c.Id <> c.Parentid 

        ) 
SELECT distinct Id, parenId, Name 

FROM name_tree 
+0

你可以只添加一列CTE像'hasChildren = case(如果存在)(从父表项的表中选择1 id = c.id then 1 else 0 end)'然后在递归CTE的第一部分给出'TableWithHiearchy'别名'c' – ZLK

+0

不确定我是否跟随你的最后一部分“然后在递归CTE的第一部分给TableWithHiearchy别名c“ –

+0

像'WITH name_tree AS(SELECT Id,Parentid,Name,ParentName,hasChildren = case exists when exists(从tablewithhierarchy中选择1,其中parentid = c.id)then 1 else 0 end FROM TableWithHiearchy AS c WHERE Parentid = 7 ' – ZLK

回答

0

我只想添加一列到查询case when exists (id is parent) then true else false end

rextester链接:http://rextester.com/RAU96705

create table TableWithHiearchy (
    id int 
    , parentid int 
    , name varchar(32) 
    , parentname varchar(32) 
) 
insert into TableWithHiearchy values 
(9,8,'nine','eight') 
,(8,7,'eight','seven') 
,(6,8,'six','eight') 
,(5,8,'five','eight') 
,(4,8,'four','eight') 
,(3,8,'three','eight') 
,(2,1,'two','one') 
,(1,1,'one','one') 
,(12,7,'tweleve','seven') 
,(11,12,'eleven','twelve'); 

with name_tree as (
    select 
     Id 
     , Parentid 
     , Name 
     , ParentName 
     , [Path]=convert(varchar(64), 
       isnull(convert(varchar(10),ParentId) + '.','') 
       + convert(varchar(10),Id) 
       ) 
    from TableWithHiearchy 
    where ParentId = 7 
    -- this is the starting point you want in your recursion 
    union all 
    select 
      c.Id 
     , c.Parentid 
     , c.Name 
     , c.ParentName --=p.Name 
     , Path=convert(varchar(64),p.Path + '.' + convert(varchar(10),c.Id)) 
     from TableWithHiearchy c 
     join name_tree p 
      on p.Id = c.ParentId -- this is the recursion 
      and c.Id <> c.Parentid 
) 
select distinct Id, parentId, Name, Path 
    , HasChildren= case 
     when exists (
      select 1 
      from name_tree i 
      where i.parentid=o.id 
      ) 
     then 'HasChildren' 
     else '' 
     end 
from name_tree o 

结果

+----+----------+---------+---------+-------------+ 
| Id | parentId | Name | Path | HasChildren | 
+----+----------+---------+---------+-------------+ 
| 3 |  8 | three | 7.8.3 |    | 
| 4 |  8 | four | 7.8.4 |    | 
| 5 |  8 | five | 7.8.5 |    | 
| 6 |  8 | six  | 7.8.6 |    | 
| 8 |  7 | eight | 7.8  | HasChildren | 
| 9 |  8 | nine | 7.8.9 |    | 
| 11 |  12 | eleven | 7.12.11 |    | 
| 12 |  7 | tweleve | 7.12 | HasChildren | 
+----+----------+---------+---------+-------------+ 

我添加的路径只是让我可以看直。

0

这是另一种选择。

在CTE 0,我们归你表(记得以您实际的表名称替换@YourTable。

在CTEP,我们建立自己的层次结构。

@Top设置为NULL ,你会得到整个层次结构,否则指定所需的顶部ID。

可以很容易地在那里你通过@Top作为参数TVF或存储过程

Declare @YourTable table (id int,parentId int,Name varchar(25),parentName varchar(25)) 
Insert Into @YourTable values 
(9, 8, 'nine' ,'eight'), 
(8, 7, 'eight' ,'seven'), 
(6, 8, 'six' ,'eight'), 
(5, 8, 'five' ,'eight'), 
(4, 8, 'four' ,'eight'), 
(3, 8, 'three' ,'eight'), 
(2, 1, 'two' ,'one'), 
(1, 1, 'one' ,'one'), 
(12, 7, 'tweleve','seven'), 
(11, 12,'eleven' ,'twelve') 

Declare @Top int   = null  --<< Sets top of Hier Try 8 or 12 
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability 

;with cte0 as (
     Select Distinct ID,ParentID,Name From @YourTable 
     Union All 
     Select Distinct ID=parentID,ParentID=NULL,Name=parentName From @YourTable where ParentID not in (Select Distinct ID From @YourTable)), 
     cteP as (
     Select Distinct 
      Seq = cast(10000+Row_Number() over (Order by ID) as varchar(500)) 
      ,ID 
      ,parentId 
      ,Name 
      ,Lvl=1 
     From cte0 
     Where IsNull(@Top,-1) = case when @Top is null then isnull(parentId,-1) else ID end 
     Union All 
     Select Seq = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.ID)) as varchar(500)) 
      ,r.ID 
      ,r.parentId 
      ,r.Name 
      ,p.Lvl+1 
     From cte0 r 
     Join cteP p on r.parentId = p.ID and r.id<>r.parentId) 
    ,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP) 
    ,cteR2 as (Select A.Seq,A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID) 
Select A.R1 
     ,B.R2 
     ,A.ID 
     ,A.parentId 
     ,A.Lvl 
     ,Title  = Replicate(@Nest,A.Lvl-1) + A.Name 
     ,HasChildren = case when A.R1<>B.R2 then 'haschildren' else '' end 
From cteR1 A 
Join cteR2 B on A.ID=B.ID 
Order By A.R1 

返回

enter image description here

现在,如果你设置@Top到,你会得到

enter image description here