Assuming I have this table : ( c
is a child of parent p
)
c p
------
40 0
2 3
2 40
3 1
7 2
1 0
Where (0
means root) — I want the order of select to be displayed as :
c b
------
1 0
3 1
2 3
40 0
2 40
7 2
That's becuase we have 2 roots (1,40) and 1 < 40.
So we start at 1
and then display below it - all it's descendants.
Then we get to 40
. same logic again.
Question:
How can I do it ?
I've succeeded to display it recursively + finding level of hierarchy*(not sure if it helps though)*
WITH cte(c, p) AS (
SELECT 40, 0 UNION ALL
SELECT 2,3 UNION ALL
SELECT 2,40 UNION ALL
SELECT 3,1 UNION ALL
SELECT 7,2 UNION ALL
SELECT 1,0
) , cte2 AS(
SELECT c,
p,
PLevel = 1
FROM cte
WHERE p = 0
UNION ALL
SELECT cte.c,
cte.p,
PLevel = cte2.PLevel + 1
FROM cte
INNER JOIN cte2
ON cte2.c = cte.p
)
SELECT *
FROM cte2
Full SQL fiddle
Right-click the hierarchy that you want to change, and then click Change Layout. Click Hierarchy, and then do one of the following: To show hierarchical relationships progressing from top to bottom and grouped hierarchically, click Labeled Hierarchy.
Use hierarchyid as a data type to create tables with a hierarchical structure, or to describe the hierarchical structure of data that is stored in another location. Use the hierarchyid functions in Transact-SQL to query and manage hierarchical data.
You have almost done it. Just add a rank
to identify each group and then sort the data on it.
Also, as you are working with more complex hierarchy we need to change the [level]
value. In is now not a number, put the full path of the current element to its parent. Where \
means parent. For example the following string:
\1\5\4\1
represents the hierarchy below:
1
--> 5
--> 4
--> 1
I get the idea from hierarchyid type. You may want to consider storing hierarchies using it, as it has handy build-in functions for working with such structures.
Here is full working example with the new data:
DECLARE @DataSource TABLE
(
[c] TINYINT
,[p] TINYINT
);
INSERT INTO @DataSource ([c], [p])
VALUES (1,0)
,(3, 1)
,(2, 3)
,(5,1)
,(7, 2)
,(40, 0)
,(2, 40);
WITH DataSource ([c], [p], [level], [rank])AS
(
SELECT [c]
,[p]
,CAST('/' AS VARCHAR(24))
,ROW_NUMBER() OVER (ORDER BY [c] ASC)
FROM @DataSource
WHERE [p] = 0
UNION ALL
SELECT DS.[c]
,DS.[p]
,CAST(DS1.[level] + CAST(DS.[c] AS VARCHAR(3)) + '/' AS VARCHAR(24))
,DS1.[rank]
FROM @DataSource DS
INNER JOIN DataSource DS1
ON DS1.[c] = DS.[p]
)
SELECT [c]
,[p]
FROM DataSource
ORDER BY [Rank]
,CAST([level] AS hierarchyid);
Again, pay attention to the node (7,2)
which is participating in the two groups (even in your example). I guess this is just a sample data and you have a way to defined where the node should be included.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With