生成用于 SQL Server hierarchyId 的唯一节点 ID
Posted
技术标签:
【中文标题】生成用于 SQL Server hierarchyId 的唯一节点 ID【英文标题】:Generating a unique node id for use with SQL Server hierarchyId 【发布时间】:2012-07-05 11:14:08 【问题描述】:设置:
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
【问题讨论】:
【参考方案1】: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 递归部分的数据集
【讨论】:
谢谢米凯尔。我正在做一些测试,因为我的层次结构非常深,产生了类似 /1/1/1/1/1/1/1/1/12 的路径 - 确保我可以获得祖先和后代。我正在考虑的一个解决方案是执行 Select *, row_number() .. as row from MyTable 进入 CTE,然后使用路径的“行”列对其进行递归 CTE,但我的递归 CTE 非常慢(结果集是〜25000行)。当我将此逻辑应用于我的代码时,我会更新。 不要使用 CTE 作为数据源进行递归 CTE。它非常慢,因为每次迭代都会重新生成第一个 CTE(带有 row_number)。如果您确实需要,最好使用临时表。 ParentNodeId 上的索引可以加快速度。以上是关于生成用于 SQL Server hierarchyId 的唯一节点 ID的主要内容,如果未能解决你的问题,请参考以下文章
有哪些 GOOD 工具可用于从 SQL Server 数据库生成 ERD? [关闭]
ORM - 特定于用于 .NET 的 SQL Server 2008+