我有一个标准表,其中包括父类,子类别关系......就像这样。
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,这些是该技术的最后一片叶子(儿童)>软件(父母),我想对任何给定父母(最后一个父母)的最后一个孩子进行排序。对于给定节点(最后一个孩子),我可以有多个父母。 我关心的是使用“排序”列对最后的孩子(叶子)进行排序。
所以基本上“经典Asp”应该在“Asp.Net”之前(我的图片中的最后一列是SORT专栏)。
我的查询很好,它按预期返回结果...只有challenege是我想要使用表中的SORT列排序最后一个NODE,最后一个节点可以有3或4个我要排序的子节点,所有节点在最后一个节点上面是它的父节点(已经是正确的顺序)。
我想要这样的输出....互联网> ISP的> CableVision(1): Verizon(2),你可以看到CableVision& Verizon的排序值为1 &安培;然后2,现在让我们说购物>优惠券>梅西斯(0):西尔斯 (2),同样的事情....我想要Macys&西尔斯要整理......而且漂亮 明显他们的父母是购物>优惠券。
@Richard aka cyberkiwi,在应用你的代码之后,我对Categories表的排序非常随机。输出低于
答案 0 :(得分: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
答案 1 :(得分: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 ;