按 "right-most" 个节点搜索 hierarchyid

Search hierarchyid by "right-most" node

我对 hierarchyid 数据类型有些陌生。我正在尝试表示给定层次结构中的实体。为了争论,假设他们是经典 "boss of" 层次结构中的人,但它可以是任何东西。

最初,我想出了一个结构,其中有一列用于实体的 id 以及它在层次结构中的位置。所以 Id 列本质上是层次结构中的 "right-most" 节点。

create table #WithId
(
    Id int primary key clustered,
    hPath hierarchyid,
    sPath as hPath.ToString()
)

insert into #WithId (Id, hPath)
values
    (1, '/1/'), (2, '/2/'), (3, '/1/3/'), (4, '/1/4/'), 
    (5, '/2/5/'), (6, '/1/6/'), (7, '/2/7/'), (8, '/2/7/8/')

我突然想到,只要 Id 列中的值与层次结构中的 "right-most" 节点相同,Id 列在技术上就是多余的.

create table #WithoutId
(
    hPath hierarchyid primary key clustered,
    sPath as hPath.ToString()
)

insert into #WithoutId (hPath)
select hPath
from #WithId

但是我仍然需要一种方法来快速查找实体并找到其上游层次结构。有了专用的 id 列,只需在该列上搜索就很简单了

declare @SomeId int = 8

-- Easy
select hPath, sPath
from #WithId
where Id = @SomeId

但是如果我没有有专门的Id专栏,我想不出一个好的方法,我需要通过最右边的节点找到行。

declare @AnotherId int = 8

-- This is totally hack, but functionally what I'm looking for
select hPath, sPath
from #WithoutId
where sPath like concat('%/', @AnotherId, '/')

有人知道这样做的好方法吗?

您可以为您的 ID 创建一个计算的和持久化的字段:

create table #WithId
(
    Hid     hierarchyid,
    HidPath as Hid.ToString(),
    Id      as cast(replace(replace(Hid.ToString(), Hid.GetAncestor(1).ToString(), ''), '/', '') as int) persisted,

    primary key (Id)
)

因此,您规范化了数据结构,搜索速度仍然很快。

但对我来说,hierarchyid 类型不仅可以显示层次结构中的位置,还可以定义项目在其父子项中的顺序。并且仅仅为了标识而使用 hierarchyid 类型是对宝贵资源的浪费,我想 :)

请阅读我关于此的文章:

https://www.codeproject.com/Articles/1192607/Combination-of-Id-ParentId-and-HierarchyId