I am having extreme difficulty constructing a query which returns an XML style hierarchy.
We have a database table which contains a hierarchy of URLs for our website. The table contains the columns: ID, URL, DisplayName, ParentID, ItemOrder
The parent ID forms a recursive relationship between the current item and it's parent. The item should site below it's parent in the hierarchy and it should also be ordered using the item order against items at the same level in the hierarchy.
I have managed to get a recursive query working so it drills down the hierarchy sequentially but I cannot order this by the item order as well.
My current query is below:
WITH Parents AS
SELECT MenuItemId, URL, ParentItemId, ItemOrder
SELECT si.MenuItemId, si.URL, si.ParentItemId, si.ItemOrder
FROM CambsMenu si INNER JOIN Parents p
ON si.ParentItemId = p.MenuItemId
SELECT DISTINCT *
Is the number of siblings a known value? Is the number of levels known? If so, you can perform operations over the ItemOrder, to guarantee that every item has a unique ItemOrder, and then just sort by that value.
For example, suppose that any item can't have more than 10 childs (ItemOrder ranges from 0 to 9) and there are at most 5 levels. What I'm going to do now, is to make the first parent ItemOrder to be 10000 time it's current item order, ant it's childer ItemOrder would be 1000 times it's current ItemOrder plus it's parent ItemOrder, and so on, removing a 0 each time you go a level down.
WITH Parents AS ( SELECT MenuItemId, URL, ParentItemId, (ItemOrder * 10000) AS ItemOrder, 10000 AS Multiplier FROM CambsMenu WHERE ParentItemId IS NULL UNION ALL SELECT si.MenuItemId, si.URL, si.ParentItemId, (p.ItemOrder + si.ItemOrder * p.Multiplier/ 10) as ItemOrder, (p.Multiplier / 10) as Multiplier FROM CambsMenu si INNER JOIN Parents p ON si.ParentItemId = p.MenuItemId ) SELECT * FROM Parents ORDER BY ItemOrder
If the number of levels or children is unknown, you can go with a similar approach but instead of building a numeric ItemOrder you can build a string ItemOrder, guaranteeing that the string '1.10.20' is lower than the string '2.1'