I have a hierarchy described by an adjacency list. There is not necessarily one root element, but I have data to identify the elements of a sheet (terminal) in hiearchy. So, the hierarchy that looked like this ...
1 - 2 - - 4 - - - 7 - 3 - - 5 - - 6 8 - 9
... will be described by a table like this. NOTE I have no way to change this format.
id parentid isleaf --- -------- ------ 1 null 0 2 1 0 3 1 0 4 2 0 5 3 1 6 3 1 7 4 1 8 null 0 9 8 1
Here is an example of a table and data definition:
CREATE TABLE [dbo].[HiearchyTest]( [id] [int] NOT NULL, [parentid] [int] NULL, [isleaf] [bit] NOT NULL ) GO INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (1, NULL, 0) INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (2, 1, 0) INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (3, 1, 0) INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (4, 2, 0) INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (5, 3, 1) INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (6, 3, 1) INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (7, 4, 1) INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (8, NULL, 0) INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (9, 8, 1) GO
From this, I must provide any identifier and get a list of all ancestors, including all descendants of each of them. So, if I imagined the input id = 6 , I would expect the following:
id descendentid -- ------------ 1 1 1 3 1 6 3 3 3 6 6 6
- id 6 just has
- its parent id id 3 would have deflectors of 3 and 6
- its parent id id 1 would have deflectors 1, 3, and 6
I will use this data to provide convolution calculations at each level of the hierarchy. This works well, assuming I can get the dataset above.
I did this using two recusive ctes - one to get a โterminalโ for each node in hiearchy. Then, the second, where I get the full ancestors of my selected node (so 6 resolves to 6, 3, 1) to go up and get a complete set. I hope that I missed something and that it can be done in one round. Here is an example of double recursion code:
declare @test int = 6; with cte as ( -- leaf nodes select id, parentid, id as terminalid from HiearchyTest where isleaf = 1 union all -- walk up - preserve "terminal" item for all levels select h.id, h.parentid, c.terminalid from HiearchyTest as h inner join cte as c on h.id = c.parentid ) , cte2 as ( -- get all ancestors of our test value select id, parentid, id as descendentid from cte where terminalid = @test union all -- and walkup from each to complete the set select h.id, h.parentid, c.descendentid from HiearchyTest h inner join cte2 as c on h.id = c.parentid ) -- final selection - order by is just for readability of this example select id, descendentid from cte2 order by id, descendentid
Additional detail : the "real" hierarchy will be much more than an example. It may technically have infinite depth, but realistically, it has rarely been to more than 10 levels.
In conclusion, my question is, can I do this with a single recursive cte instead of rewriting the hierarchy twice.