1

设置 :

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

问题 :

无论如何我可以在一个 CTE 接受的表单中实现一个路径 hierarchyId::Parse() 吗?例如 /1/2/3/

TIA

4

1 回答 1

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小提琴

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

CTE 中关于分析和聚合函数的遗漏

更新 2:
显然这个解决方案可以安全使用,因为它记录在 MSDN 上。
WITH common_table_expression (Transact-SQL)

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

于 2012-07-05T14:20:03.753 回答