从 table 获取所有子节点

Get all child nodes from table

我正在尝试从 table 获取所有子节点,但我的查询获取了一些额外的结果,我不确定为什么

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 的地方)0 的 ParentID 是树视图中的根节点。

Table

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

因为tblcategory WHERE [pkID] = 6 底部select 需要相同的where 语句。没有它,您将获得整个 table.

的 children

所以这样的事情应该可行:

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 的所有 children、grand children、great grand children 等。

;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  

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

该查询可以简化为

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

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

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