棘手的选择声明

Seb*_*Seb 3 sql t-sql sql-server select

我有一个包含类别的表,每个类别都有一个ID,一个名称和一个ParentID.问题是有3个级别,父类别,子类别和子类别.

我可以使用simple SELECT和a WHERE ParentID IS NULL子句提取父类别:

SELECT *
FROM Category
WHERE ParentID IS NULL
Run Code Online (Sandbox Code Playgroud)

但是,WHERE ParentID IS NOT NULL子句将返回子类别和子类别.

我正在寻找一种方法来只提取子类别,只提取子类别.

Mah*_*mal 5

通常,对于这些类型的问题,最好使用使用公用表表达式递归查询.像这样的东西:

;WITH CategoriesTree(CategoryID, CategoryName, ParentName, CategoryLevel)
AS
(
   SELECT 
     c.ID, 
     c.Name, 
     CAST('No Parent' AS VARCHAR(50)) AS ParentName, 
     0 AS CategoryLevel
   FROM @Categories c
   WHERE c.ParentID IS NULL
   UNION ALL
   SELECT c.ID, c.Name, p.CategoryName, p.CategoryLevel + 1
   FROM CategoriesTree p
   INNER JOIN @Categories c ON c.ParentID = p.CategoryID
)
SELECT * 
FROM CategoriesTree
Where CategoryLevel = some id;
Run Code Online (Sandbox Code Playgroud)

SQL小提琴演示

这会给你:

CATEGORYID       CATEGORYNAME         PARENTNAME      CATEGORYLEVEL
    1         Root Cateogry         No Parent               0
    2         Sub Cateogry 1        Root Cateogry           1
    3         Sub Cateogry 2        Root Cateogry           1
    4         Sub Cateogry 3        Root Cateogry           1
    8         sub Cateogry 1 of 3   Sub Cateogry 3          2
    7         Sub Cateogry 1 of 2   Sub Cateogry 2          2
    5         Sub Cateogry 1 of 1   Sub Cateogry 1          2
    6         sub Cateogry 2 of 1   Sub Cateogry 1          2
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?

使用此查询,您可以控制要选择的类别级别.例如,对于我在上一个演示中使用的示例数据,这里是类别树:

                        1: RootCategory                Category Level:  0
                               |
                               |
                 ---------------------------- 
                 |             |            |
                 |             |            |
              2: Sub1        3: Sub2      4: sub3      Category Level:   1
                 |             |            |
          ------------         |            |
          |          |         |            |
          |          |         |            |
     5: Sub1of1  6: Sub2of1   7: sub1of2   8: sub1of3  Category Level:   2
Run Code Online (Sandbox Code Playgroud)

此查询将为您提供具有新生成CategoryLevel列的此类别树.

请注意:在我在演示中使用的示例数据中,只有一个父类别(具有parentidIS NULL 的类别).但是,如果有很多父类别,查询将工作正常.这是因为CTE的锚点查询,它是:

SELECT 
     c.ID, 
     c.Name, 
     CAST('No Parent' AS VARCHAR(50)) AS ParentName, 
     0 AS CategoryLevel
FROM @Categories c
WHERE c.ParentID IS NULL;
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用生成的列CategoryLevel仅选择您感兴趣的级别的子类别.

例如,如果您需要选择只有根类的第一子类的子类,你可以使用谓词得到这些类别CategoryLevel = 2:

;WITH CategoriesTree(CategoryID, CategoryName, ParentName, CategoryLevel)
AS
(
    ...
)
SELECT * 
FROM CategoriesTree
WHERE CategoryLevel = 2;
Run Code Online (Sandbox Code Playgroud)

这会给你:

CATEGORYID       CATEGORYNAME         PARENTNAME      CATEGORYLEVEL
    8        sub Cateogry 1 of 3    Sub Cateogry 3          2
    7        Sub Cateogry 1 of 2    Sub Cateogry 2          2
    5        Sub Cateogry 1 of 1    Sub Cateogry 1          2
    6        sub Cateogry 2 of 1    Sub Cateogry 1          2
Run Code Online (Sandbox Code Playgroud)

SQL小提琴演示