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

通常、この種の問題については、共通テーブル式を使用した再帰クエリを使用することをお勧めします。そのようなもの:

;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ます。

注意:デモで使用したサンプル データでは、親カテゴリは 1 つだけでした ( 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

第 1 レベルのカテゴリ - あなたはそれを持っています:

SELECT *
FROM Category
WHERE ParentID IS NULL

第 2 レベルのカテゴリについては、次を試すことができます。

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

3 番目の場合:

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)

完全に最適ではないかもしれませんが、うまくいくようです。行数が比較的少なく、レベルが 3 つしかない場合は、それで十分です。

于 2012-12-06T07:48:51.117 に答える