收集在 SQL 服务器中的关系 table 中捕获的树中的所有节点

Collect all the nodes in a tree captured within a relational table in SQL Server

我有一个具有以下架构的 table:

CREATE TABLE Feature 
(
    FeatureId INT IDENTITY(1,1),
    ParentFeatureId INT,
    TargetObjectType VARCHAR(64)
)

如您所见,它定义了一个特征树。我有兴趣收集在给定节点下找到的所有后代。

我目前的解决方案对我来说似乎很尴尬:

IF OBJECT_ID('tempdb..#features') IS NOT NULL
    DROP TABLE #features

SELECT 
    0 FeatureId, TargetObjectType, ParentFeatureID
INTO 
    #features
FROM 
    Feature 
WHERE 
    1 = 0

INSERT INTO #features
    SELECT 
        FeatureId, TargetObjectType, ParentFeatureID
    FROM 
        Feature
    WHERE 
        TargetObjectType IN ('Root1', 'Root2')

WHILE @@ROWCOUNT > 0
    INSERT INTO #features
        SELECT FeatureId, TargetObjectType, ParentFeatureID
        FROM Feature f
        WHERE ParentFeatureID IN (SELECT FeatureId FROM #features) 
          AND NOT EXISTS (SELECT 1 FROM #features WHERE FeatureId = f.FeatureId)

SELECT * FROM #features

有没有更优雅的方法呢?也许使用递归 CTE?

数据量不大(最多几千条记录)。所有数据都代表一个只有几个层次结构的森林,最多说 7 个。

这是一个递归 CTE,它会为您提供 child 节点,无论您作为顶部参数传入的任何 FeatureId。如果您只想要 children,请将 cte 的第一个 select 语句中的 WHERE 子句更改为 WHERE e.ParentFeatureId = @lookupFeatureId 而不是 WHERE e.FeatureId = @lookupFeatureId

DECLARE @lookupFeatureId INT; SET @lookupFeatureId = 6;

WITH cte (FeatureId, ParentFeatureId, TargetObjectType, [Level])
AS
(
    SELECT e.FeatureId, e.ParentFeatureId, e.TargetObjectType, 0 AS Level
    FROM Feature AS e
    WHERE e.FeatureId = @lookupFeatureId

    UNION ALL

    SELECT e.FeatureId, e.ParentFeatureId, e.TargetObjectType, d.[Level] + 1
    FROM Feature AS e
    INNER JOIN cte AS d
    ON e.ParentFeatureId = d.FeatureId
)
SELECT FeatureId, ParentFeatureId, TargetObjectType, [Level]
FROM cte