A common table expression (CTE) is similar to a derived table in that it is not stored as an object and lasts only for the duration of the query. Unlike a derived table, a CTE can be self-referencing and can be referenced multiple times in the same query.
Using Common Table Expression to traverse the adjacency List (parent / child) Model.
WITH StructureLevels
AS
(
-- base
SELECT
StructureId,
ParentStructureId,
SortOrder,
(CONVERT(VARCHAR(MAX)
, REPLICATE ('0', 6-Len(CAST(SortOrder as Varchar)))) + CONVERT(VARCHAR(MAX), SortOrder))
AS thePath,
1 AS Level
FROM DocumentStructure
WHERE
StructureId = @RootStructureId
UNION ALL
-- recursive
SELECT
DS.StructureId,
DS.ParentStructureId,
DS.SortOrder,
SL.thePath + '.'
+ CONVERT(VARCHAR(MAX)
, REPLICATE ('0', 6-Len(Cast(DS.SortOrder as Varchar)))) + CONVERT(VARCHAR(MAX), DS.SortOrder)
AS thePath,
SL.Level + 1 AS Level
FROM StructureLevels SL
JOIN DocumentStructure DS
ON DS.ParentStructureId = SL.StructureId
),
StructureRows AS
(
SELECT
StructureLevels.*,
ROW_NUMBER() OVER (ORDER BY thePath) AS Row
FROM StructureLevels
)
SELECT ER.StructureId,
ER.ParentStructureId,
ER.SortOrder,
ER.thePath,
ER.Level NodeLevel,
(ER.Row * 2) - ER.Level AS NodeLeft,
((ER.Row * 2) - ER.Level) +
(
SELECT COUNT(*) * 2
FROM StructureRows ER2
WHERE ER2.thePath LIKE ER.thePath + '.%'
) + 1 AS NodeRight
FROM StructureRows ER