Reputation: 148534
I have a CTE query which looks for main leafs and sub leafs. but I'm having trouble controling the leaf selection order between 2 siblings :
Each row in the table is declared as :
(childID INT ,parentID INT ,NAME NVARCHAR(30),location int)
Where location
is a priority to sort IFF they are siblings.
And so I have this tree structure : those pairs has a location priority :
For example :
`a` ( location=1) should be before `f` (location=2)
`b` ( location=1) should be before `e` (location=2)
`d` ( location=1) should be **before** `c` (location=2)
The problem is that it seems that I must first order by
childID
in order to see the right structure ( sibling unsorted).
But - what how does my order by
should look like so I will be able to see the right structure (&& sibling sorted) ?
(in my example : d
should come before c
)
Here is the working query which yields all the tree leafs ( unsorted siblings)
p.s. childID
is not indicating anything about the sorting. it's just a placeholder. as I said , the location between 2 brothers is by the location
column.( here , childId is sorted because thats the order of which i inserted the rows...
Upvotes: 4
Views: 3001
Reputation: 15816
The following is i-one's answer modified, at Royi Namir's request, to use left-padded numeric strings for the path:
;WITH CTE AS(
SELECT childID, parentID, 0 AS depth, NAME , location,
Cast( Right( '00000' + Cast( Location as VarChar(6) ), 6 ) as VarChar(1024) ) as Path
FROM @myTable
WHERE childID = parentID
UNION ALL
SELECT TBL.childID, TBL.parentID,
CTE.depth + 1 , TBL.name ,TBL.location,
Cast( cte.Path + '.' + Right( '00000' + Cast( Tbl.Location as VarChar(6) ), 6 ) as VarChar(1024) )
FROM @myTable AS TBL
INNER JOIN CTE ON TBL.parentID = CTE.childID
WHERE TBL.childID<>TBL.parentID
)
SELECT depth, childID, parentID, location, REPLICATE('----', depth) + name
FROM CTE
ORDER BY path
NB: Untested and written on vacation.
The separators (.
) are not required, but make the resulting values easier to read and may simplify some operations, e.g. finding common sub-paths.
Upvotes: 3
Reputation: 5120
You can calculate path of the tree node in your CTE and use it for sorting
;WITH CTE AS(
SELECT childID, parentID, 0 AS depth, NAME , location,
cast(location as varbinary(max)) path
FROM @myTable
WHERE childID = parentID
UNION ALL
SELECT TBL.childID, TBL.parentID,
CTE.depth + 1 , TBL.name ,TBL.location,
cte.path + cast(TBL.location as binary(4))
FROM @myTable AS TBL
INNER JOIN CTE ON TBL.parentID = CTE.childID
WHERE TBL.childID<>TBL.parentID
)
SELECT depth, childID, parentID, location, REPLICATE('----', depth) + name
FROM CTE
ORDER BY path
Upvotes: 6