3

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

我可以用一个简单的SELECT和一个WHERE ParentID IS NULL子句来提取父类别:

SELECT *
FROM Category
WHERE ParentID IS NULL

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

我正在寻找一种仅提取子类别和子类别的方法。

4

3 回答 3

5

通常,对于这类问题,最好使用Recursive Queries Using Common Table Expressions。像这样:

;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;

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

这是如何运作的?

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

                        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

此查询将为您提供带有新生成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;

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

例如,如果您只需要选择根类别的第一个子类别的子类别,您可以使用谓词获取这些类别CategoryLevel = 2

;WITH CategoriesTree(CategoryID, CategoryName, ParentName, CategoryLevel)
AS
(
    ...
)
SELECT * 
FROM CategoriesTree
WHERE CategoryLevel = 2;

这会给你:

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

SQL 小提琴演示

于 2012-12-06T08:04:08.330 回答
2

第一级类别 - 你有它:

SELECT *
FROM Category
WHERE ParentID IS NULL

对于二级类别,您可以尝试:

SELECT * FROM Category
WHERE ParentID IN (SELECT ID FROM Category WHERE ParentID IS NULL).

对于第三个:

SELECT * FROM Category
WHERE ParentID IN (SELECT ID FROM Category WHERE ParentID IS NOT NULL)

(未测试)

于 2012-12-06T07:45:35.610 回答
1

怎么样:

-- Root parents
select c.* from categories c where c.ParentID is null

-- Second level. Select where parentid is a root category.
select c.* from categories c 
where c.ParentID in (select c1.ID from categories c1 where c1.ParentID is null);

-- Third level. Select where parentid is a second level category
with second_level_cats (ID) as (
  select c.ID from categories c 
  where c.ParentID in (select c1.ID from categories c1 where c1.ParentID is null)
  )
select c.* from categories c 
where c.ParentID in (select l2.ID from second_level_cats l2)

可能不是完全最佳的,但它似乎有效。如果只有相对较少的行数并且您只会进入三个级别,那么它就足够了。

于 2012-12-06T07:48:51.117 回答