生成用于SQL Server hierarchyId的唯一节点标识

时间:2012-07-05 11:14:08

标签: sql common-table-expression hierarchyid

设置:

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

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

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

问题:

我可以使用CTE生成我的层次结构与节点和父节点,但我需要一个路径传递给hierarchyid :: Parse() - 不幸的是,Z123456形式的nodeid不解析。如果NodeId和ParentNodeId是行id整数,我会打包并把我的火车赶回家去看我可爱的妻子,但相反,我在这里盯着3360 x 1050分辨率。

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

;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

问题:

无论如何我可以在表单层次结构中实现路径:Id :: Parse()将接受一个CTE吗?例如/ 1/2/3 /

TIA

1 个答案:

答案 0 :(得分: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上有记录 WITH common_table_expression (Transact-SQL)

  

CTE的递归部分中的分析和聚合函数是   应用于当前递归级别的集合而不是集合   对于CTE。像ROW_NUMBER这样的函数只对子集有效   数据通过当前递归级别而不是整个传递给它们   数据集用于CTE的递归部分