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