我有一个包含类别的表,每个类别都有一个ID,一个名称和一个ParentID。问题是有3个级别,父类别,子类别和子类别。
我可以使用简单的SELECT
和WHERE ParentID IS NULL
子句提取父类别:
SELECT *
FROM Category
WHERE ParentID IS NULL
但是,WHERE ParentID IS NOT NULL
子句将同时返回子类别和子类别。
我正在寻找一种方法来只提取子类别,而只提取子类别。
答案 0 :(得分: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;
这会给你:
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
列的此类别树。
请注意:在我在演示中使用的示例数据中,只有一个父类别(parentid
的类别为IS 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
答案 1 :(得分: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)
(未经测试)
答案 2 :(得分: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)
可能不是完全最佳但似乎有效。如果只有相对较少的行数,而你只需要达到三个级别那么就足够了。