Reputation: 1432
I have table with hierarchical, parent-child relations and want to order it by that hierarchy. Table is:
id|parent|type
--------------
1 |0 |1
2 |0 |1
3 |0 |1
4 |0 |2
5 |0 |2
6 |2 |2
7 |3 |2
And as result I want this:
id|parent|type
--------------
1 |0 |1
2 |0 |1
6 |2 |2
3 |0 |1
7 |3 |2
4 |0 |2
5 |0 |2
So I want get something like a tree view where type 1 ordered first and type 2 at the end.
Now I'm trying to use recursion but the order is wrong:
with cte as
(
select id, parent, type from tbl where id=1
union all
select id, parent, type,
ROW_NUMBER()over(
order by
(case when t.type = 1 then 1
when t.type = 2 then 2
else 1000
end) as rn
from tbl t
inner join cte c on c.id=t.parent
)
select * from cte
order by rn
How can I do this?
Upvotes: 6
Views: 7569
Reputation: 5743
Using the order by hierarchyid
with cte is simple, not test for recursive relations
DECLARE @Data table (Id int identity(1,1) primary key, Parent int, Type int)
INSERT @Data VALUES
(0, 1),
(0, 1),
(0, 1),
(0, 2),
(0, 2),
(2, 2),
(3, 2)
SELECT * FROM @Data
;WITH level AS
(
-- The root, build the hierarchy by /{Type}.{Id}/, where Type is important then Id
SELECT *, -- 0 AS Level,
'/' + CONVERT(varchar(max), Type + 0.1 * Id) + '/' AS Ordering
FROM @Data
WHERE Parent = 0
UNION ALL
-- Connect the parent with appending the hierarchy
SELECT d.*, -- c.Level + 1,
c.Ordering + CONVERT(varchar(max), d.Type + 0.1 * d.Id) + '/'
FROM @Data d INNER JOIN level c ON d.Parent = c.Id
)
SELECT Id, Parent, Type FROM level
ORDER BY CAST(Ordering as hierarchyid) -- The key part to convert data type
Upvotes: 3
Reputation: 1070
with cte as
(
select *, 1 level, row_number() over (order by id) rn
from tbl
where parent = 0
union all
select t.*, cte.level + 1 level, cte.rn
from cte
inner join tbl t on cte.id = t.parent
)
select id, parent, type from cte order by rn, level
Upvotes: 0
Reputation: 46361
Can be done with the following recursive CTE:
WITH cte AS (
SELECT *,
CAST(ROW_NUMBER() OVER(ORDER BY id) AS REAL) rn,
1 level
FROM tbl
WHERE parent = 0
UNION ALL
SELECT t2.*,
cte.rn + (CAST(ROW_NUMBER() OVER(ORDER BY t2.id) AS REAL) / POWER(10, cte.level)) rn,
cte.level + 1 level
FROM tbl t2 INNER JOIN cte
ON t2.parent = cte.id
)
SELECT id, parent, type
FROM cte
ORDER BY rn
See SQLFiddle with more complicated sample data (deeper hierarchies, "unordered parent-child id's")
Upvotes: 8