2012-07-05 57 views
1

设置:用于生成与SQL Server使用一个唯一的节点ID HIERARCHYID

MyTable (
    NodeId varchar(10), 
    ParentNodeId varchar(10), 
    NodeName varchar(50) 
) 

的NodeId不是数字,可以采取任何形式。多数的形式是Z123456,但有些是12345.

我想为我的分层需求使用SqlServer HierarchyId数据类型。

问题:

我可以用一个CTE来生成我的节点和父层次,但我需要一个路径传递到HIERARCHYID ::解析() - 遗憾的是,在形式Z123456一个NODEID不解析。如果NodeId和ParentNodeId是行ID整数,我会收拾起来,赶上我的火车回家看看我可爱的妻子,但相反,我在这里盯着3360 x 1050分辨率。

我正在使用CTE来生成我的层次结构(并且我也可以在CTE中创建一个路径),然后我附加行号给我独特的整数ID,但是我将不得不重新运行使用生成的Ids生成我的路径的分层CTE。

;with o as (
    select n.ParentNodeID, n.nodeid, n.NodeName, 1 as [level] 
    from Mytable n where n.ParentNodeID is null 
     union all 
    select n.ParentNodeID, n.nodeid, n.NodeName, o.[level] + 1 as [Level] 
    from MyTable n inner join o on n.ParentNodeID = o.NodeID 
) 
select NodeID, ParentNodeID, NodeDescription 
    , ROW_NUMBER() over (order by [level]) as hNodeId 
from o 

问:

反正我有可以实现的形式HIERARCHYID ::解析(路径)将与一个CTE接受?例如/ 1/2/3/

TIA

回答

3
with C as 
(
    select T.NodeId, 
     T.ParentNodeId, 
     cast('/'+cast(row_number() over(order by T.NodeId) as varchar(10)) as varchar(max)) as HID 
    from MyTable as T 
    where T.ParentNodeId is null 
    union all 
    select T.NodeId, 
     T.ParentNodeId, 
     C.HID+'/'+cast(row_number() over(order by T.NodeId) as varchar(10)) 
    from MyTable as T 
    inner join C 
     on T.ParentNodeId = C.NodeId 
) 
select NodeId, 
     ParentNodeId, 
     HID, 
     hierarchyId::Parse(HID+'/') 
from C 
order by HID 

SQL-Fiddle

更新:
的研究的位表明,使用在递归CTE解析函数是不允许的。它在我的测试中有效,但如果我能想出替代解决方案,我会更新这个答案。

Omission about analytic and aggregate functions in CTEs

更新2:
显然,这种解决方案是安全的使用,因为它是在MSDN文档。在CTE的递归部分
WITH common_table_expression (Transact-SQL)

解析与聚集函数也 施加到该组当前递归层次,而不是该组 为CTE。像ROW_NUMBER功能只对当前递归级别传递给他们 数据,而不是整个 集pased的CTE

+0

感谢的Mikael的递归部分数据的子集进行操作。我正在做一些测试,因为我的层次非常深,产生了一个像/ 1/1/1/1/1/1/1/1/12这样的路径 - 确保我可以得到祖先和后代。我想到的一个解决方案是从MyTable到一个CTE做一个Select *,row_number()..作为行,然后在该行上使用'row'列做递归CTE,但是我的递归CTE非常慢(结果集是〜25000行)。当我将这个逻辑应用于我的代码时,我会进行更新。 – 2012-07-05 15:43:02

+0

不要做一个使用CTE作为数据源的递归CTE。它非常慢,因为每次迭代都会重新生成第一个CTE(带有row_number)。如果你真的需要这样做,最好使用临时表。 – 2012-07-05 15:48:58

+0

ParentNodeId上的索引可能会加速一点。 – 2012-07-05 15:51:08