Reputation: 2952
I am using T/SQL in Microsoft SQL Server 2008
I have a table
CREATE TABLE [TestTable](
[CHILD] [int] NOT NULL,
[PARENT] [int] NOT NULL
) ON [PRIMARY]
GO
These are some values which define a parent child hierarchial relationship
CHILD PARENT
1 2
2 0
3 1
4 2
5 0
Visually, this table looks like this
0
2
1
3
4
5
I would ideally like the values to be shown as follows (where the right hand column indicates the generation)
CHILD GENERATION
0 0
2 1
1 2
3 3
4 2
5 1
My T/SQL code looks like this
with n(CHILD, PARENT, GENERATION) as (
select CHILD, PARENT,1 as GENERATION from TestTable
where PARENT=0
union all
select nplus1.CHILD, nplus1.PARENT, GENERATION+1 from TestTable as nplus1, n
where nplus1.PARENT=n.CHILD
)
select CHILD,GENERATION from n
However it doesn't work!
It returns
CHILD GENERATION
2 1
5 1
1 2
4 2
3 3
It has the right generation, but the wrong sort order! Does anyone have any ideas how to solve this?
Thank you!
Upvotes: 4
Views: 22523
Reputation: 171
Based on AakashM's solution I'm proposing a solution that will be a bit more general, because it is using row_number to build the hierarchy instead of using the column values.
Here is it:
;with n(CHILD, PARENT, GENERATION, hierarchy) as (
select CHILD, PARENT,0, CAST(CHILD as nvarchar) as GENERATION from @t
where PARENT=-1
union all
select nplus1.CHILD, nplus1.PARENT, GENERATION+1,
cast(hierarchy + '.' + CAST(cast(ROW_NUMBER() over (order by nplus1.CHILD) as int) as nvarchar) as nvarchar)
from
@t as nplus1 inner join n on nplus1.PARENT=n.CHILD
)
select CHILD,GENERATION,hierarchy
from n
order by hierarchy
returns:
CHILD GENERATION hierarchy
0 0 0
2 1 0.1
1 2 0.1.1
3 3 0.1.1.1
4 2 0.1.2
5 1 0.2
Upvotes: 0
Reputation: 63340
You'll need your recursion to also build something that can be sorted by at the end:
declare @t TABLE (
[CHILD] [int] NOT NULL,
[PARENT] [int] NOT NULL
)
insert @t values
( 0, -1), -- I added this
( 1, 2 ),
( 2, 0 ),
( 3, 1 ),
( 4, 2 ),
( 5, 0 )
(note I have added a true root element)
;with n(CHILD, PARENT, GENERATION, hierarchy) as (
select CHILD, PARENT,0, CAST(CHILD as nvarchar) as GENERATION from @t
where PARENT=-1
union all
select nplus1.CHILD, nplus1.PARENT, GENERATION+1,
cast(n.hierarchy + '.' + CAST(nplus1.child as nvarchar) as nvarchar)
from
@t as nplus1 inner join n on nplus1.PARENT=n.CHILD
)
select CHILD,GENERATION
from n
order by hierarchy
returns
CHILD GENERATION
----------- -----------
0 0
2 1
1 2
3 3
4 2
5 1
Including the hierarchy
for illustration:
CHILD GENERATION hierarchy
----------- ----------- ------------------------------
0 0 0
2 1 0.2
1 2 0.2.1
3 3 0.2.1.3
4 2 0.2.4
5 1 0.5
Depending on how big your ids get, you might have to do stuff with left-padding with zeroes to get the sorting right.
Note that SQL 2008 has a built-in hierarchy
type for this kind of thing...
Upvotes: 7