我有一个包含类别的表,每个类别作为一个 ID、一个名称和一个 ParentID。问题是有3个级别,父类别,子类别和子类别。
我可以用一个简单的SELECT
和一个WHERE ParentID IS NULL
子句来提取父类别:
SELECT *
FROM Category
WHERE ParentID IS NULL
但是,WHERE ParentID IS NOT NULL
子句将返回子类别和子类别。
我正在寻找一种仅提取子类别和子类别的方法。
我有一个包含类别的表,每个类别作为一个 ID、一个名称和一个 ParentID。问题是有3个级别,父类别,子类别和子类别。
我可以用一个简单的SELECT
和一个WHERE ParentID IS NULL
子句来提取父类别:
SELECT *
FROM Category
WHERE ParentID IS NULL
但是,WHERE ParentID IS NOT NULL
子句将返回子类别和子类别。
我正在寻找一种仅提取子类别和子类别的方法。
通常,对于这类问题,最好使用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
第一级类别 - 你有它:
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)
(未测试)
怎么样:
-- 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)
可能不是完全最佳的,但它似乎有效。如果只有相对较少的行数并且您只会进入三个级别,那么它就足够了。