2012-09-24 57 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