Solved

CTE to list all children per node in hierarchy

Posted on 2011-02-14
11
1,032 Views
Last Modified: 2012-05-11
ParentChildTb
ID    Parent
004  003
003  002
002  001
001  001
Desired Output:
Parent Child
001  002
001  003
001  004
002  003
002  004
003  004
I need a query that traverses through a tree and gets all children, grandchildren, etc. per item
Each item can have many children on different levels and each child can have multiple parents.

Thank you!
0
Comment
Question by:larisa1970
  • 4
  • 3
  • 2
11 Comments
 
LVL 143

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 34889608
this should do:
with data as (
  select id, parent from ParentChildTb t where not exists ( select null from ParentChildTb x where x.id = t.Parent )
 UNION ALL
 select t.id, t.parent from ParentChildTb t join data on data.id = t.parentid
)
select * from data

Open in new window

0
 

Author Comment

by:larisa1970
ID: 34890242
Angelll,
thanks, but you query doesn't return anything.
It should return more records than in the original table
0
 
LVL 143

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 34890469
sorry, I see:
with data as (
  select id, parent from ParentChildTb t where id = parent)
 UNION ALL
 select t.id, t.parent from ParentChildTb t join data on data.id = t.parentid
)
select * from data

Open in new window

0
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 

Author Comment

by:larisa1970
ID: 34890605

"The statement terminated. The maximum recursion 100 has been exhausted before statement completion."
0
 
LVL 40

Expert Comment

by:Sharath
ID: 34890907
check this.
-- @ParentChildTb1 is your main table
declare @ParentChildTb1 table(ID int,Parent int)
insert @ParentChildTb1 values(4,3)
insert @ParentChildTb1 values(3,2)
insert @ParentChildTb1 values(2,1)
insert @ParentChildTb1 values(1,1)

-- Create a temp table, insert all the records from your main table and update the rool to NULL 
declare @ParentChildTb table(ID int,Parent int)
insert @ParentChildTb select * from @ParentChildTb1
update @ParentChildTb set Parent = NULL where ID = Parent

-- Try this CTE to get the Tree of parents
;WITH cte AS(
SELECT ID, Parent, coalesce(Convert(varchar(max),Parent)+',','') AS Tree
  FROM @ParentChildTb
 WHERE Parent is null
 UNION ALL
SELECT c.ID, c.Parent, p.Tree + ',' + CAST(c.Parent AS varchar(max))
  FROM @ParentChildTb c
  JOIN cte p
    ON c.Parent = p.ID
),cte2 as (
SELECT ID,Parent,SUBSTRING(Tree,2,LEN(Tree)) Tree FROM cte)
-- This query gives the desired output
select ParentID,ID ChildID from (
SELECT ID,ltrim(SUBSTRING(Tree, n, CHARINDEX(',', Tree + ',',n) - n)) AS ParentID
 FROM cte2
CROSS JOIN (SELECT number FROM master..spt_values WHERE type = 'P')  AS Numbers(n)
WHERE SUBSTRING(',' + Tree, n, 1) = ','
  AND n < LEN(Tree) + 1) t1
order by ParentID,ID
/*
ParentID	ChildID
1	2
1	3
1	4
2	3
2	4
3	4
*/

Open in new window

0
 
LVL 143

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 34892392
of course...
with data as (
  select id, parent from ParentChildTb t where id = parent)
 UNION ALL
 select t.id, t.parent from ParentChildTb t join data on data.id = t.parentid and t.id <> t.parentid
)
select * from data

Open in new window

0
 
LVL 40

Accepted Solution

by:
Sharath earned 500 total points
ID: 35014757
I am not sure why did you accept http:#34892392. First thing is there are syntactical errors in that query. Forget about syntax errors. The query is not producing the expected result.
declare @ParentChildTb1 table(ID int,Parent int)
insert @ParentChildTb1 values(4,3)
insert @ParentChildTb1 values(3,2)
insert @ParentChildTb1 values(2,1)
insert @ParentChildTb1 values(1,1)

;with data as (
  select id, parent from @ParentChildTb1 t where id = parent
 UNION ALL
 select t.id, t.parent from @ParentChildTb1 t join data on data.id = t.Parent and t.id <> t.Parent
)
select * from data
/*
id	parent
1	1
2	1
3	2
4	3
*/

Open in new window

0
 
LVL 40

Expert Comment

by:Sharath
ID: 35031780
I would suggest Option #3: Accept one or more comments as the solution.The correct answer would be http:#a34890907
0
 
LVL 143

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 35034194
well, when I analyse the question in deep, even Sharath's code will not solve all the scenarios properly without an additional distinct.

>Each item can have many children on different levels and each child can have multiple parents.
this was not in the test case neither, and will result in duplicates.

I presumed the asker was happy with the simple code ...


so my suggestion would be to split between the original accepted comment and Sharath's comment
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
SQL Server Degrading on Write 13 70
T-SQL to Update Table Dynamically 2 55
Move SQL 2005 Express to Server 2012R2 19 142
Analysis of table use 7 54
by Mark Wills Attending one of Rob Farley's seminars the other day, I heard the phrase "The Accidental DBA" and fell in love with it. It got me thinking about the plight of the newcomer to SQL Server...  So if you are the accidental DBA, or, simp…
Introduction: When running hybrid database environments, you often need to query some data from a remote db of any type, while being connected to your MS SQL Server database. Problems start when you try to combine that with some "user input" pass…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

792 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question