使用 HIERARCHYID 创建面包屑导航?

问题描述 投票:0回答:2

我在 Microsoft SQL Server 中有

Product Categories
表:

类别ID(身份) 节点(HIERARCHYID) 类别名称 (NVARCHAR(100)
1 0x 产品
2 0x58 主要类别1
3 0x68 主类2
4 0x5AC0 子类别 1A
5 0x5B40 子类别 1B

我想显示每个类别的面包屑,例如子类别 1A:

Products > Main Category 1 > Subcategory 1A

我是否使用递归 CTE,就好像存在自连接 (

ParentID
) 而不是
HIERARCHYID
,或者这与
HIERARCHYID
的工作方式不同吗?我在互联网上找到的所有有关面包屑的材料都假设使用
ParentID
,而不是
HIERARCHYID

您能给我举个例子吗?

谢谢你。

sql-server common-table-expression hierarchy hierarchyid
2个回答
1
投票

您将始终需要递归 CTE,除非您在创建或更新层次结构时预先计算面包屑。

您可以使用

.GetAncestor(1)
列上的
Node
获取家长 ID。

过滤 CTE,以便最终结果仅返回已递归到顶部的行。

WITH cte AS (
    SELECT
      t.*,
      BreadCrumb = CAST(t.CategoryName AS nvarchar(max)),
      ParentNode = t.Node.GetAncestor(1)
    FROM YourTable t

    UNION ALL

    SELECT
      cte.CategoryID,
      cte.Node,
      cte.CategoryName,
      CONCAT(t.CategoryName, ' -> ', cte.BreadCrumb),
      t.Node.GetAncestor(1)
    FROM cte
    JOIN YourTable t ON t.Node = cte.ParentNode
)
SELECT *
FROM cte
WHERE cte.ParentNode IS NULL;

db<>小提琴


0
投票

鉴于您已经在使用hierarchyid,您拥有从给定类别一直向上返回层次结构所需的一切。首先,一个表值函数将给定的 Hierarchyid 分解为其所有组成部分:

create or alter function decomposeHierarchy(@h hierarchyid)
returns table
as
return
    select h = @h.GetAncestor(n-1)
    from dbo.Numbers as n
    where n.n <= @h.GetLevel()+1;
go

其中

dbo.Numbers
只是一个从 1 开始的计数表。注意 - TVF 定义中的 ±1 是我的计数表从 1 开始而
GetLevel
是从 0 开始的结果。另请注意 - 如果您愿意,您可能可以使用 GENERATE_SERIES 而不是计数表。我过去还曾编写过一个小型 CLR 函数来进行此分解。

一旦我们有了分解层次结构的方法,将构成的层次结构ID连接回源数据并将它们连接在一起就很简单了。

declare @t table (
    CategoryID int,
    [Node] hierarchyid,
    CategoryName varchar(100)
);

insert into @t 
    (CategoryID, [Node], CategoryName)
values 
    (1, 0x,'Products'),
    (2, 0x58,'Main Category 1'),
    (3, 0x68,'Main Category 2'),
    (4, 0x5AC0,'Subcategory 1A'),
    (5, 0x5B40,'Subcategory 1B');

declare @CategoryID int = 5;
declare @h hierarchyid = (
    select [Node]
    from @t
    where CategoryID = @CategoryID
);
select STRING_AGG(CategoryName, ' > ') within group (order by c.[Node].GetLevel())
from dbo.decomposeHierarchy(@h) as d
join @t as c
    on d.h = c.[Node];
© www.soinside.com 2019 - 2024. All rights reserved.