Controlling the sibling order under recursive CTE?

…衆ロ難τιáo~ 提交于 2019-12-19 04:00:27

问题


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...


回答1:


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



回答2:


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.



来源:https://stackoverflow.com/questions/18036417/controlling-the-sibling-order-under-recursive-cte

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!