在 SQL Server 中使用 With Union 的 SQL 构建路径

标签 sql sql-server recursion

这是 SQL Server 问题

我有一组类别,它们的关系导致嵌套类别。

我想建立一条保持关系的途径并建立 SEF 网址。这是我正在寻找的内容:

Category table: 
ID, Name
1, Root
2, Cat1
3, Cat2
4, Cat1.1
5, Cat1.2
6, Cat2.1
7, Cat2,2

CategoryChild table: ParentCategoryID, ChildCategoryID
1, 2
1, 3
2, 4
2, 5
3, 6
3, 7

这是一个无限嵌套的结构。这就是我正在做的事情(我知道这是错的,但想要这样的事情):

WITH  MenuItems
    AS (

        SELECT  

        CAST((ItemPath) AS VARCHAR(1000)) AS 'ItemPath',
        CategoryID, Category, ChildID
        FROM    #Mapping
        WHERE   CategoryID = 1
        UNION ALL
        SELECT  
                CAST((items.ItemPath + '-/' + MenuItem.Category) AS VARCHAR(1000)) AS 'ItemPath',
                MenuItem.CategoryID, MenuItem.Category, MenuItem.ChildID
        FROM     #Mapping AS MenuItem
                JOIN MenuItems AS items
                  ON items.ChildID = MenuItem.CategoryID 
       ) 
select * from MenuItems

它给了我这样的东西:

root--------|1---|root---|2
root--------|1---|root---|3
root/Cat2---|3---|Cat2---|6
root/Cat2---|3---|Cat2---|7
root/Cat1---|2---|Cat1---|4
root/Cat1---|2---|Cat1---|5

所以理想的路径应该是这样的:

根/父/子(等等)!

最佳答案

我不确定这是否是您正在寻找的内容,但我过去曾使用过递归 cte,因此这可能有助于构建项目路径。

注意:我已经添加了附加信息,例如每个项目的根 ID 和级别,以便您可以更改输出的顺序。

declare @Category table (Id int, Name varchar(10))
insert into @Category values (1, 'Root'),(2, 'Cat1'), (3, 'Cat2'), (4, 'Cat1.1'), (5, 'Cat1.2'), (6, 'Cat2.1'), (7, 'Cat2.2')

declare @CategoryChild table (ParentCategoryID int, ChildCategoryID int)
insert into @CategoryChild values (1, 2), (1, 3), (2, 4), (2, 5), (3, 6), (3, 7)

;with cte as 
(
    -- root part
    select 
        ccParent.ChildCategoryID Id,
        ccParent.ParentCategoryID ParentId,
        c.Name Name,
        CAST(parentCategory.Name + '/' + c.Name as varchar(1000)) as Path,
        ccParent.ChildCategoryID Root,
        0 as Level
    from
        @CategoryChild ccParent
    inner join
        @Category c on c.Id = ccParent.ChildCategoryID
    inner join
        @Category parentCategory on parentCategory.Id = ccParent.ParentCategoryID
    where
        ccParent.ParentCategoryID = 1

    union all

    -- recursive part
    select
        ccChild.ChildCategoryID Id,
        ccChild.ParentCategoryID ParentId,
        c.Name Name,
        CAST((cte.Path + '/' + c.Name) as varchar(1000)) as Path,
        cte.Root Root,
        cte.Level + 1 as Level
    from
        @CategoryChild ccChild
    inner join
        @Category c on c.Id = ccChild.ChildCategoryID
    inner join
        cte on cte.Id = ccChild.ParentCategoryID
)
select cte.Path 
from cte 
order by cte.Root, cte.Level

在我的环境中运行上述内容会产生以下结果

Root/Cat1
Root/Cat1/Cat1.1
Root/Cat1/Cat1.2
Root/Cat2
Root/Cat2/Cat2.1
Root/Cat2/Cat2.2

如果您希望将根类别作为独立项目包含在结果集中,则可以更改 cte 的第一部分以对根项目的选择进行硬编码。

;with cte as 
(
    -- root part
    select 
        c.Id Id,
        null ParentId,
        c.Name Name,
        CAST(c.Name as varchar(1000)) as Path,
        c.Id Root,
        0 as Level
    from
        @Category c
    where 
        c.Name = 'Root'

    union all

    ... same as before

给出以下内容

Root
Root/Cat1
Root/Cat1/Cat1.1
Root/Cat1/Cat1.2
Root/Cat2
Root/Cat2/Cat2.1
Root/Cat2/Cat2.2

关于在 SQL Server 中使用 With Union 的 SQL 构建路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10564367/

相关文章:

c++ - 递归函数中由信号 SIGSEGV(地址边界错误)终止

sql - 在 SQL Server 中将两列相乘

sql - 触发器是否只能用于 SQL 无法实现的操作?

sql - 如果一条记录包含特定值,如何排除整个组?

sql - Azure SQL DB 备份策略说明

sql-server - 在 SQL Server 中为每条记录创建行到列

sql - 查看以识别分组值或对象

java - sql 在简单查询中抛出错误

javascript - 如何在 javascript 中使用递归来创建键值对象

java - 对递归方法和循环感到困惑