sql - 如何使用邻接表中的数据创建闭包表?

标签 sql sql-server hierarchy transitive-closure-table

我有一个数据库,其中包含使用邻接列表模型存储的类别层次结构。

层次结构深 3 层(不包括虚构的根节点),包含大约 1700 个节点。第二层和第三层的节点可以有多个父节点。多对多关系使用一个附加表,如下所示:

CREATE TABLE dbo.Category(
    id int IDENTITY(1,1) NOT NULL,
    name varchar(255) NOT NULL,
)

CREATE TABLE dbo.CategoryHierarchy(
    relId int IDENTITY(1,1) NOT NULL,
    catId int NOT NULL,
    parentId int NOT NULL,
)

如果我转向使用传递闭包表方法(出于数据完整性等原因),是否有一个相对简单的查询可以执行来生成闭包表的值? (使用 SQL Server 2005)

我浏览过文章和演示文稿,例如 Bill Karwin 的 Models for hierarchical data但它只对单个节点进行插入查询,我需要很长时间才能创建这样的树。

谢谢。

编辑:
CategoryHierarchy表中的RelID纯粹是为了主键,与Category表的节点id无关。

另外,闭包表是指这样的表:

CREATE TABLE ClosureTable (
    ancestor int NOT NULL,
    descendant int NOT NULL,
    [length] int NOT NULL,
)

其中前两列是复合主键,并且是 Category.id 的单独外键。

最佳答案

我试图弄清楚同样的事情,但希望在递归 CTE 中得到它。这对你来说是行不通的(SQL Server 2008+),但对于其他人来说,这就是我最终得到的结果。

关键是 anchor 不是您的根节点(其中 parent_id IS NULL),而是闭包中的所有零深度行表。

表格

CREATE TABLE dbo.category (
    id         INT IDENTITY(1, 1) NOT NULL,
    parent_id  INT                    NULL
)

数据

INSERT INTO dbo.category (id, parent_id)
VALUES
    (1, NULL),
    (2, 1),
    (3, 1),
    (4, 2)

热膨胀系数

WITH category_cte AS
(
    SELECT
        id AS ancestor,
        id AS descendant,
        0  AS depth
    FROM dbo.category

    UNION ALL

    SELECT
        CTE.ancestor  AS ancestor,
        C.id          AS descendant,
        CTE.depth + 1 AS depth
    FROM dbo.category AS C
    JOIN category_cte AS CTE
        ON C.parent_id = CTE.descendant
)
SELECT * FROM category_cte

结果

ancestor descendant depth
-------- ---------- -----
1        1          0     <- anchor query
2        2          0
3        3          0
4        4          0
2        4          1     <- first recursive query
1        2          1
1        3          1
1        4          2     <- second recursive query

关于sql - 如何使用邻接表中的数据创建闭包表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12621873/

相关文章:

iPhone - 在父 View Controller 中调用方法

java - 如何检测大型项目中两种方法之间的确切流程

sql - 需要帮助理解 SQL 中的 JOINS

sql - rails 包含不同的值

sql - 如何从Sql Server表中获取列名和其他信息?

sql-server - SQLServer 何时在 Select 中应用 UPDLOCK

sql-server - 使用 Switch 的报告服务表达式

xml - WPF - 基于另一个 xmlns 定义一个 xmlns

sql - Delphi:如何将列表作为参数传递给 SQL 查询?

sql - 使用 SQL 选择行 n 次