【问题标题】:Generate hierarchical path (SQL Server)生成分层路径 (SQL Server)
【发布时间】:2021-08-27 16:35:53
【问题描述】:

我有一个classstructure 表:

create table classstructure (classstructureid int, classificationid varchar(25), parent int);

insert into classstructure(classstructureid, classificationid, parent) values(1001, 'FLEET', null);
insert into classstructure(classstructureid, classificationid, parent) values(1002, 'LIGHTDUTYVEHICLE', 1001);
insert into classstructure(classstructureid, classificationid, parent) values(1004, 'MEDIUMDUTYVEHICLE', 1001);
insert into classstructure(classstructureid, classificationid, parent) values(1022, 'ACTIVETRANSPORTATION', null);
insert into classstructure(classstructureid, classificationid, parent) values(1023, 'FACILITYWALKWAY', 1022);
insert into classstructure(classstructureid, classificationid, parent) values(1024, 'TRAIL', 1022);
insert into classstructure(classstructureid, classificationid, parent) values(1085, 'SIDEWALK', 1022);
insert into classstructure(classstructureid, classificationid, parent) values(1091, 'SDWRAMP', 1085);


CLASSSTRUCTUREID CLASSIFICATIONID              PARENT
---------------- ------------------------- ----------
            1001 FLEET                               
            1002 LIGHTDUTYVEHICLE                1001
            1004 MEDIUMDUTYVEHICLE               1001

            1022 ACTIVETRANSPORTATION                
            1023 FACILITYWALKWAY                 1022
            1024 TRAIL                           1022
            1085 SIDEWALK                        1022
            1091 SDWRAMP                         1085

我想创建一个将记录折叠到层次结构路径的查询:

HIERARCHYPATH
---------------------------
FLEET
FLEET \ LIGHTDUTYVEHICLE
FLEET \ MEDIUMDUTYVEHICLE 

ACTIVETRANSPORTATION
ACTIVETRANSPORTATION \ FACILITYWALKWAY
ACTIVETRANSPORTATION \ TRAIL
ACTIVETRANSPORTATION \ SIDEWALK
ACTIVETRANSPORTATION \ SIDEWALK \ SDWRAMP

如何使用 SQL 做到这一点?

【问题讨论】:

    标签: sql-server parent-child hierarchical-data sql-server-2019


    【解决方案1】:

    简短回答:这可以使用递归 CTE 来完成。这是 StackOverflow 上的另一个答案,我在其中回答了这个问题:Account Hierarchy Salesforce Accounts - SQL Server

    详细说明:您的数据结构是将分层数据存储在数据库中的经典方式。递归 CTE 将从某个点开始并递归循环,直到条件不再为真(找到所有孩子),因此得名;递归的。有一些免责声明,例如递归的限制(它执行多少轮),但如果需要可以减轻。

    【讨论】:

      【解决方案2】:

      这将是一个标准的递归 CTE。 CTE 非常适合中小型层次结构,但是,如果您的层次结构很大,那么还有其他使用临时表的技术会更高效。

      注意:HierID 列是可选的。它只是提供了一个适当的顺序

      示例或dbFiddle

      ;with cteP as (
            Select [CLASSSTRUCTUREID]
                  ,[Parent] 
                  ,[CLASSIFICATIONID]
                  ,[HIERARCHYPATH] = convert(varchar(500),[CLASSIFICATIONID])
                  ,[HierID]        = convert(hierarchyid,concat('/',[CLASSSTRUCTUREID],'/'))
            From   classstructure 
            Where  [Parent] is null
            Union  All
            Select [CLASSSTRUCTUREID]  = r.[CLASSSTRUCTUREID]
                  ,[Parent]            = r.[Parent] 
                  ,[CLASSIFICATIONID]  = r.[CLASSIFICATIONID]
                  ,[HIERARCHYPATH]     = convert(varchar(500),concat(p.[HIERARCHYPATH],' \ ',r.[CLASSIFICATIONID]))
                  ,[HierID]            = convert(hierarchyid,concat(p.HierID.ToString(),r.[CLASSSTRUCTUREID],'/'))
            From   classstructure  r
            Join   cteP p on r.[Parent]  = p.[CLASSSTRUCTUREID])
      Select [CLASSSTRUCTUREID]
            ,[Parent]
            ,[CLASSIFICATIONID]
            ,[HIERARCHYPATH]
       From cteP A
       Order by [HierID]
      

      结果

      就个人而言,我喜欢在最终结果中包含层次结构 LEVEL。在最终的 SELECT 中,您可以包括:

      ...
      [Level]   = HierID.GetLevel()
      ...
      

      【讨论】:

        【解决方案3】:

        给你:

        with CTE_Rec as
        (
            select 
                cast(classificationid as varchar(500)) classificationid, 
                classstructureid 
            from classstructure 
            where parent is null
            
            union All
            
            Select 
                cast(b.classificationid+' \ '+a.classificationid as varchar(500)),
                a.classstructureid
            from classstructure a 
            inner join CTE_REC b on b.classstructureid = a.parent 
        ) 
        Select 
            classificationid 
        from CTE_Rec
        order by classificationid
        

        【讨论】:

          猜你喜欢
          • 2020-01-21
          • 2011-10-30
          • 1970-01-01
          • 1970-01-01
          • 2015-04-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多