0

我有一个标准表,它与父、子类别关系......就像这样。

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

输出如下图:

在此处输入图像描述

查找值为 ASP.NET 和 CLASSIC ASP 的行,这些是技术 > 软件(父级)的最后一个叶子(子级),我想对任何给定父级(最后一个父级)的 LAST CHILDREN 进行排序。对于给定节点(最后一个孩子),我可以有多个父母,我关心的是使用“排序”列对最后一个孩子(叶子)进行排序。

所以基本上“Classic Asp”应该在“Asp.Net”之前(最后一列是我图像中的 SORT 列)。

我的查询很好,它按预期返回结果......唯一的挑战是我想使用表中的 SORT 列对最后一个节点进行排序,最后一个节点可以有 3 或 4 个我想要排序的子节点,所有节点都在最后一个节点之上节点是它的父母(它们的顺序已经正确)。

我想要这样的输出.... Internet > ISP's > CableVision (1) : Verizon (2) 如您所见 CableVision 和 Verizon 的排序值为 1 和 2,现在假设我们有购物 > 优惠券 > Macys(0 ) : Sears (2),同样的事情....我希望对 Macys & Sears 进行分类...而且很明显他们的父母是购物 > 优惠券。

@Richard aka cyberkiwi,在应用您的代码后,我对类别表的排序非常随机。输出低于 在此处输入图像描述

4

2 回答 2

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
于 2012-09-24T08:17:13.493 回答
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 ;
于 2012-09-24T08:19:50.720 回答