从表中获取所有子节点

时间:2016-06-29 15:08:13

标签: sql parent-child

我正在尝试从表中获取所有子节点,但我的查询正在获取一些额外的结果,我不知道为什么

SELECT [pkID]
    ,[parentID]
    ,[CategoryName]
FROM [tblCategory]
WHERE [pkID] = 6
UNION ALL
SELECT [Sub].[pkID]
    ,[Sub].[ParentID]
    ,[Sub].[CategoryName]
FROM [tblCategory] [Sub]
INNER JOIN [tblCategory] AS [Sub2] ON [Sub].[ParentID] = [Sub2].[pkID]

运行此查询时,我正在获取其他子节点 注意*在我的VB.Net应用程序中(需要调用此SQL的地方)ParentID为0是树视图中的根节点。

pkID | ParentID | CategoryName
1    | 6        | Category1
2    | 0        | Category2
3    | 0        | Category3
4    | 0        | Category4
5    | 0        | Category5
6    | 0        | Category6
7    | 0        | Category7
8    | 0        | Category8
9    | 7        | Category9

结果

pkID | parentID | CategoryName
6    | 0        | Category6
1    | 6        | Category1
9    | 7        | Category9 <-- not a child of pkID=6

3 个答案:

答案 0 :(得分:5)

这是因为您需要在tblcategory WHERE [pkID] = 6的底部选择中使用相同的where语句。没有它你会得到整个桌子的孩子。

所以这样的事情应该有效:

SELECT [pkID]
    ,[parentID]
    ,[CategoryName]
FROM [tblCategory]
WHERE [pkID] = 6
UNION ALL
SELECT [Sub].[pkID]
    ,[Sub].[ParentID]
    ,[Sub].[CategoryName]
FROM [tblCategory] [Sub]
INNER JOIN [tblCategory] AS [Sub2] ON [Sub].[ParentID] = [Sub2].[pkID]
WHERE [sub].[pkID] = 6

简化为Juan注意到,我应该想到可以在同一个select语句中作为单个where条件完成。

SELECT [pkID]
    ,[parentID]
    ,[CategoryName]
FROM [tblCategory]
WHERE [pkID] = 6
     or ParentId = 6

这是一个递归的cte方法,可以让所有的孩子,大孩子,大孩子等都成为一个parentid。

;WITH cte AS (
    SELECT [pkID]
       ,[parentID]
       ,[CategoryName]
       -- ,1 AS [Level]
    FROM [tblCategory]
    WHERE [pkID] = 6


    UNION ALL

    SELECT
       t.pkId
       ,t.[parentID]
       ,t.CategoryName
       -- ,[Level] + 1 AS [Level]
    FROM
       [tblCategory] t
       INNER JOIN cte c
       ON t.ParentId = c.pkId
)

SELECT *
FROM cte  

答案 1 :(得分:1)

看起来你试图做一个递归的cte,但后来你改变主意。

该查询可以简化为

SELECT [pkID]
    ,[parentID]
    ,[CategoryName]
FROM [tblCategory]
WHERE [pkID] = 6
   OR [ParentID] = 6

答案 2 :(得分:1)

假设第二个节点也可能有子节点,我建议使用递归查询。像这样(未经测试):

DECLARE @SearchID int = 6;

WITH cteTree AS(
SELECT pkID, parentID, CategoryName
  FROM tblCategory
  WHERE pkID = @SearchID
UNION ALL
SELECT pt.pkID, pt.parentID, pt.CategoryName
  FROM tblCategory AS pt
  JOIN cteTree AS ct ON ct.pkID = pt.parentID
)
SELECT *
  FROM cteTree