2017-01-19 81 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