I change a little the source so that we have the item A99
as first object (prevSiblingID
=-1). In this way , we can test the output is in order of prevSiblingID
DECLARE @tvH TABLE
(itemID INT,
label VARCHAR(50),
parentID INT,
prevSiblingID INT,
nextSiblingID INT)
INSERT INTO @tvH(itemID,label,parentID,prevSiblingID,nextSiblingID)
VALUES(10,'B',-1,50,20),
(20,'C', -1, 10, -1),
(30, 'B1', 10 ,-1 ,40),
(40, 'B2', 10, 30, -1),
(50, 'A', -1 ,-1 ,10),
/*(60, 'A1', 50, -1, 70),
(70, 'A2', 50, 60, -1),
(80, 'A21', 70, -1, -1),*/
(60, 'A99', 50, -1, 70),
(70, 'A1', 50, 60, -1),
(80, 'A12', 70, -1, -1),
(90, 'C1', 20, -1, -1),
(100, 'Z', 0, -1, -1)
--SELECT * FROM @tvH
;WITH cteR
AS (
SELECT itemID,label,-1 AS ParentID, label as Path
, prevSiblingID,nextSiblingID
FROM @tvh
WHERE parentID = 0
UNION ALL
SELECT T.itemID,T.label,R.itemID, CAST(R.Path + '.'+ T.label AS VARCHAR(50)) AS Path
, T.prevSiblingID,T.nextSiblingID
FROM (SELECT itemID,label,ParentID, label as Path, prevSiblingID,nextSiblingID FROM @tvh WHERE parentID = 0 ) AS R
CROSS JOIN (SELECT itemID,label,ParentID , prevSiblingID,nextSiblingID FROM @tvh WHERE parentID = -1 ) AS T
)
--SELECT * fROM cteR
,cteR2
AS(
SELECT itemID,label,ParentID, CAST(Path AS VARCHAR(50)) AS Path, prevSiblingID,nextSiblingID
,CAST(Path AS VARCHAR(50)) AS PathParent
FROM cteR
UNION ALL
SELECT T.itemID,T.label,T.ParentID, CAST(R.Path + '.'+ T.label AS VARCHAR(50)) AS Path, T.prevSiblingID,T.nextSiblingID
, CAST(R.Path AS VARCHAR(50))
FROM @tvh AS T
INNER JOIN cteR2 AS R
ON R.itemID = T.parentID
)
,cteR3
AS (SELECT *
,ROW_NUMBER()OVER(PARTITION BY ParentID ORDER BY prevSiblingID ASC) AS rn_Asc
,ROW_NUMBER()OVER(PARTITION BY ParentID ORDER BY nextSiblingID ASC) AS rn_Desc
,LEN(Path)-LEN(REPLACE(Path,'.','')) AS lvl
FROM cteR2)
SELECT
itemID,label,ParentID,Path
--*
FROM cteR3
ORDER BY PathParent,lvl,rn_Asc,rn_Desc--,lvl
The output:
itemID label ParentID Path
100 Z -1 Z
50 A 100 Z.A
60 A99 50 Z.A.A99
70 A1 50 Z.A.A1
80 A12 70 Z.A.A1.A12
10 B 100 Z.B
30 B1 10 Z.B.B1
40 B2 10 Z.B.B2
20 C 100 Z.C
90 C1 20 Z.C.C1