2012-09-24 80 views
0

我有一個標準的表,這sotres父,子類別關係...像這樣。遞歸查詢排序

id, parent, catName, sort 

而且我用下面的查詢來創建一個遞歸樹

;WITH cte AS (
    SELECT 0 AS lvl, id, catName, parent,levels,sort, 
     CAST(id AS VARCHAR(128)) AS path 
    FROM CategoriesMap WHERE parent =0 
    UNION ALL 
    SELECT p.lvl + 1, c.id, c.catName, c.parent,c.levels,c.sort, 
     CAST(p.path + '_' + CAST(c.id AS VARCHAR) AS VARCHAR(128)) 
    FROM CategoriesMap c 
    INNER JOIN cte p ON p.id = c.parent 
) 
SELECT 
    id, 
    catName AS catName, 
    lvl, 
    levels, 
    path, 
    parent, 
    sort 
FROM cte 
ORDER BY path 

,輸出是這樣的形象:

enter image description here

尋找與價值ASP的行。 NET & CLASSIC ASP,這些是技術的最後一片葉子(孩子)>軟件(父母),我想對任何給定父項的最後一個孩子進行排序(最後一位父母)。我可以有一個給定節點的多個父母(最後一個孩子)& 我所關心的是使用「排序」列排序LAST Children(leaf)。

如此基本的「經典Asp」應該在「Asp.Net」之前(最後一列是我的圖片中的SORT列)。

我的查詢很好,它按照預期返回結果......只有challenege是我想要使用表中的SORT列排序最後的NODE,最後一個節點可以有3或4個我想排序的子元素,全部最後一個節點之上的節點是它的父節點(它們的順序已經是正確的)。

I want output like this.... Internet > ISP's > CableVision (1) : Verizon (2) as you can see CableVision & Verizon have Sort Value of 1 & then 2, Now lets say we have Shopping > Coupons > Macys(0) : Sears (2), same thing....I want Macys & Sears to be sorted...and its pretty obvious their parents are Shopping > Coupons.

@Richard又名cyberkiwi,將你的代碼後,我的分揀分​​類表是很隨意的。輸出低於 enter image description here

+0

我不同意它是隨機的。 11,13,14都是葉子。他們首先出現在分支(1,12分支)之前,甚至在他們自己內部排序。同樣,1_3和1_4出現在1_2_ *之前,因爲它們是葉子,並且(1_3/1_4在內部排序)。如果你想要答案給你你所期望的,你*需要*學會先告訴*你的期望。從最後一張圖片開始,不要只是告訴我們這是錯誤的。告訴我們它應該是什麼樣子。 – RichardTheKiwi

+0

我的道歉,如果我不能正確解釋。請查看ID「1」及其排序值(即1),其父母爲頂級父母類別。另外ID「2」應該在ID「3」之前,如果您查看他們的排序列值,您會注意到排序關閉。 – highwingers

+0

我有一種感覺,除非您發佈的圖像顯示從最後一幅圖像中給出的確切樣本所需的確切結果,否則您不會看到有關此問題的任何其他操作。 – RichardTheKiwi

回答

1

延緩path的計算爲一個電平,所以最終結果集具有可用父路徑(ppath):

;WITH cte AS (
    SELECT 0 AS lvl, id, catName, parent,levels,sort, 
     CAST('' AS VARCHAR(128)) AS ppath 
    FROM CategoriesMap WHERE parent =0 
    UNION ALL 
    SELECT p.lvl + 1, c.id, c.catName, c.parent,c.levels,c.sort, 
     CAST(p.ppath + '_' + CAST(p.id AS VARCHAR) AS VARCHAR(128)) 
    FROM CategoriesMap c 
    INNER JOIN cte p ON p.id = c.parent 
) 
SELECT 
    id, 
    catName, 
    lvl, 
    levels, 
    CAST(ppath + '_' + CAST(id AS VARCHAR) AS VARCHAR(128)) AS path, 
    parent, 
    sort 
FROM cte 
ORDER BY 
    CASE WHEN sort IS NULL 
      THEN path 
      ELSE ppath 
    END 
    , sort ; 

不確定爲什麼上面給出錯誤。這不會:

ORDER BY 
    CASE WHEN sort IS NULL 
     THEN CAST(ppath + '_' + CAST(id AS VARCHAR) AS VARCHAR(128)) 
     ELSE ppath 
    END 
    , sort ; 
+0

這個查詢在我父母= 12(這是技術類別)的地方做了TRICK,在我父母= 0的情況下(我將返回所有父母和他們的子節點)。 – highwingers

+0

@highwingers:你是否嘗試過修正? –

+0

是的,出現錯誤:列名'路徑'無效。我認爲我們到了那裏,只有當我可以把孩子放在他們的頂級分類下。 – highwingers

1

這個SQL Fiddle應該給你你所需要的。 訣竅的確是當你將樹葉與樹枝混合在一起時。在我的解決方案中,葉子總是出現在樹枝之前,葉子內部(即使與樹枝相互混合),它們當然按sort列排序。

DDL

create table CategoriesMap(
    id int, parent int, catname varchar(20), sort int); 
insert CategoriesMap select 
    1, 0, 'Activities', null union all select 
    2, 0, 'Property', null union all select 
    3, 2, 'For rent', null union all select 
    4, 2, 'For sale', null union all select 
    12, 0, 'Technology', 3 union all select 
    15, 12, 'Hardware', null union all select 
    21, 12, 'Phones', null union all select 
    22, 15, 'Computers', null union all select 
    18, 12, 'Software', null union all select 
    19, 18, 'Asp.net', 2 union all select 
    20, 18, 'SQL', 3 union all select 
    23, 18, 'Php', 4 union all select 
    24, 18, 'Classic ASP', 1; 

查詢

;WITH leaves AS (
    SELECT A.id 
     FROM CategoriesMap A 
LEFT JOIN CategoriesMap B ON A.id=B.parent 
    WHERE B.id is null 
) 
,cte AS (
    SELECT 0 AS lvl, id, catName, parent,sort, 
      CAST(id AS VARCHAR(MAX)) AS path, 
      '/'+CAST(id AS VARCHAR(MAX))+'/' AS hier 
     FROM CategoriesMap 
    WHERE parent =0 
UNION ALL 
    SELECT p.lvl + 1, c.id, c.catName, c.parent,c.sort, 
      p.path + '_' + CAST(c.id AS VARCHAR(MAX)), 
      p.hier + CAST(c.id AS VARCHAR(MAX)) + '/' 
     FROM CategoriesMap c 
     JOIN cte p ON p.id = c.parent 
) 
    SELECT c.id, 
      c.catName, 
      c.lvl, 
      --levels, 
      c.path, 
      --c.hier, 
      c.parent, 
      c.sort 
     FROM cte c 
LEFT JOIN leaves l on l.id=c.id 
    ORDER BY CASE WHEN l.id is null 
       then cast(hier as hierarchyid) 
       else cast(hier as hierarchyid).GetAncestor(1) 
       END, 
      CASE WHEN l.id is null then 0 else 1 end, 
      sort 
+0

嘿嘿,我們有同樣的想法:) –

+0

這打破了整個表的排序,我的查詢很好,它返回的結果如預期...只有challenege是我想排序最後一個NODE使用SORT列在表中,最後一個節點可以有3或4個我想排序的子節點,最後一個節點上面的所有節點都是它的父節點(它們的順序已經正確)。 – highwingers

+0

是的,我試過了,如果我通過一個類別,例如PARENT = 12,它就會起作用。我想返回所有類別和他們的孩子。用你的榜樣......所有的父母都在TOP,然後所有的孩子都在他們之下。如果查詢可以返回樹類型輸出,並且只有最後一個根據SORT列排序的葉子,那麼它會很好。 – highwingers