优化收集所有相关项目的查询

vic*_*cky 5 sql-server

下表是我的菜单主​​表,菜单深度不受限制。每个菜单可以有一个子菜单和一个子子菜单等等。

我面临的问题是获取具有相同顶级父级的所有项目。

一种解决方案是在父级不为空时进行循环,第二种解决方案是创建一个具有父级 id 的视图以及所有带有逗号分隔列的子菜单 id。

然后一个选择命令将给出父 ID。我的表如下:

CategoryID  | ParentID    
1           | null        
2           | null        
3           | 1           
4           | 1           
5           | 2           
6           | 2           
7           | 3           
Run Code Online (Sandbox Code Playgroud)

输出应该是

CategoryID  | AllRelatedCategory
1           | 1,3,4,7
2           | 2,5,6
Run Code Online (Sandbox Code Playgroud)

我当前的代码如下。问题是它仅适用于 3 个层次结构。

;with cte as
(
select a.CategoryID col1, convert(varchar, a.CategoryID) col2, a.ParentID
from [dbo].[TB_CATEGORY_MASTER] a where a.ParentID is null

union
select a.CategoryID col1, (convert(varchar, isnull(b.CategoryID,''))) col2, a.ParentID
from [dbo].[TB_CATEGORY_MASTER] a 
left join [dbo].[TB_CATEGORY_MASTER] b on a.CategoryID=b.ParentID

union
select a.CategoryID col1, (convert(varchar, isnull(c.CategoryID,''))) col2, a.ParentID
from [dbo].[TB_CATEGORY_MASTER] a 
left join [dbo].[TB_CATEGORY_MASTER] b on a.CategoryID=b.ParentID
left join [dbo].[TB_CATEGORY_MASTER] c on b.CategoryID=c.ParentID
)

select distinct c.col1, 
  STUFF(
         (SELECT distinct ', ' + c1.col2
          FROM cte c1
          where c.col1 = c1.col1
          FOR XML PATH ('')), 1, 1, '') col2
from cte c
where c.ParentID is null
Run Code Online (Sandbox Code Playgroud)

Dav*_*itz 1

with    cte
        as
        (
            select      CategoryID  as root_CategoryID
                       ,1           as lvl
                       ,CategoryID


            from        TB_CATEGORY_MASTER

            where       ParentID is null


            union all


            select      c.root_CategoryID
                       ,c.lvl + 1
                       ,t.CategoryID

            from                    TB_CATEGORY_MASTER  as t

                        join        cte                 as c

                        on          c.CategoryID = t.ParentID
            )

select     t.CategoryID

          ,(select      case when lvl = 1 then '' else ',' end 
                      + cast (c.CategoryID as varchar(10))

            from        cte as c

            where       c.root_CategoryID = t.CategoryID

            order by    lvl

            for xml path('')
            )                   as AllRelatedCategory

from        TB_CATEGORY_MASTER  as t

where       ParentID is null
Run Code Online (Sandbox Code Playgroud)
+------------+--------------------+
| CategoryID | AllRelatedCategory |
+------------+--------------------+
|          1 | 1,3,4,7            |
|          2 | 2,5,6              |
+------------+--------------------+
Run Code Online (Sandbox Code Playgroud)