Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 How to flatten a hierarchical table?

Author  Topic 

phrankbooth
Posting Yak Master

162 Posts

Posted - 2012-02-25 : 10:06:14
Here's my table layout

ChildID|ChildName|ParentID|ParentName
1 |Parent1 |NULL |NULL
2 |Parent2 |NULL |NULL
3 |Child1 |1 |Parent1
4 |Child2 |2 |Parent2
5 |GndChild1 |3 |Child1
6 |GndChild2 |4 |Child2


I'd like the output to be this:
Row1: Parent1, Child1, GndChild1
Row2: Parent2, Child2, GndChild2

Any ideas appreciated, thanks!

I'm on 2008 R2.


--PhB

sunitabeck
Master Smack Fu Yak Hacker

5155 Posts

Posted - 2012-02-25 : 10:32:59
If you have only 3 levels as you have in the example you can join the same table 3 times as shown in the query below. If you have a large/unknown number of levels, you can do similar things using a recursive CTE. If you want to list parents who don't have any children and grandchildren, you would need to use left joins.
SELECT
a.ChildName,
b.ChildName,
c.ChildName
FROM
YourTable a
INNER JOIN YourTable b ON a.ChildId = b.ParentId
INNER JOIN YourTable c ON b.ChildId = c.ParentId
WHERE
a.ParentId IS NULL;
Go to Top of Page

phrankbooth
Posting Yak Master

162 Posts

Posted - 2012-02-25 : 10:36:22
Thanks for you r prompt response, I actually have a large/unknown number of levels. What would this query look like then?

I know about CTE, the problem I'm having is I don't know how to extend out the table columns for each new level in the hierarchy.

--PhB
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2012-02-25 : 13:04:29
quote:
Originally posted by phrankbooth

Thanks for you r prompt response, I actually have a large/unknown number of levels. What would this query look like then?

I know about CTE, the problem I'm having is I don't know how to extend out the table columns for each new level in the hierarchy.

--PhB


for that you've to use dynamic sql. why not use CTE to put the results onto a temporary table with level indicator( to see how far level goes)

then create a new table based on these levels to create required number of grandchild columns

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

sunitabeck
Master Smack Fu Yak Hacker

5155 Posts

Posted - 2012-02-25 : 13:35:16
To add some color to what Visakh was suggesting, what I meant by using recursive CTE is something like what I am showing below. I am still using a static pivot - you can extend it even if you have a large number of levels, but if you have an unknown number of levels, you would need dynamic pivoting. Take a look at Madhivanan's blog for a dynamic pivot function.

-- My simplified test table----------------------------------------------
CREATE TABLE #tmp (cid INT , cname VARCHAR(32), pid INT, pname VARCHAR(32))

INSERT INTO #tmp VALUES
(1,'p1',NULL,NULL),(2,'p2',NULL,NULL),(3,'c1',1,'p1'),(4,'c2',2,'p2'),(5,'g1',3,'c1'),(6,'g2',4,'c2');

-- Recursive query-------------------------------------------------------
;WITH cte AS
(
SELECT
*,
ROW_NUMBER() OVER (ORDER BY cid) AS RN,
1 AS lvl
FROM #tmp a
WHERE
NOT EXISTS (SELECT * FROM #tmp b WHERE a.cid = b.pid)

UNION ALL

SELECT
t.*,
c.RN,
c.lvl+1
FROM
#tmp t
INNER JOIN cte c ON t.cid = c.pid
),
cte2 AS
(
SELECT cname, lvl, RN FROM cte
)
--- Static pivoting------
SELECT
*
FROM
cte2
PIVOT
( MAX(cname) FOR lvl IN ([1],[2],[3])) P;

-- CLEANUP -------------------------------------------------------
DROP TABLE #tmp;
BTW, it should/would work even if you have multiple children/grandchildren, and even if there are people with and without children at the same level - but I have not tested those.
Go to Top of Page
   

- Advertisement -