2017-04-17 65 views
0

关系表内捕获我有一个表与下面的架构树的所有节点:收集在SQL Server

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个。

+0

是递归CTE可能是这里最好的选择。 –

+0

看看http://stackoverflow.com/questions/18106947/cte-recursion-to-get-tree-hierarchy,如果你想编写递归CTE的帮助。 –

回答

0

下面是一个递归CTE,它将为您提供任何FeatureId的子节点作为参数在顶部传入。如果你只想要孩子,更改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