【问题标题】:Recursive CTE SQL (Parent Child)递归 CTE SQL(父子)
【发布时间】:2017-08-16 14:45:41
【问题描述】:

我使用的是 SQL Server 2012

LOCATIONDETAIL 表

OID     LOCATIONNAME    PARENTID
1           GLOBAL          0
2           NORTH           1
3           SOUTH           1
4           NORTH1          2
5           SOUTH1          3

LOCATIONSITECONFIG 表

OID LOCATIONID  SITENAME
1       2        TEST

我使用递归 CTE 查询

;WITH LOCALSITEHIERARCHY AS
(
    SELECT  A.OID
            ,A.PARENTOID
            ,CAST(A.LOCATIONNAME + ' ( ' + LSC.SITENAME + ' )' AS NVARCHAR(100)) AS NAME
            ,LSC.OID AS SITEOID
    FROM LOCATIONDETAIL A
            INNER JOIN LOCATIONSITECONFIG LSC 
                ON LSC.LOCATIONDETAILOID = A.OID                
    WHERE
            LSC.SITENAME <> 'GLOBAL' AND LSC.RECSTATUS = 'A'
    UNION ALL
    SELECT 
        A.OID
        ,A.PARENTOID
        ,CAST(A.LOCATIONNAME AS NVARCHAR(100))                  
        ,LH.SITEOID 
    FROM LOCATIONDETAIL A 
        INNER JOIN LOCALSITEHIERARCHY LH ON A.PARENTOID = LH.OID
)

SELECT * FROM LOCALSITEHIERARCHY

NORTH 现在是 Global 中的一个单独站点。此查询以树结构返回 North 和 North 1,这没问题。

当我将 Global 作为一个新站点时,我不想将 North 作为 Global 站点的一部分。

例如,添加名为 (NEWTEST) 的站点 2,它是全局的

LOCATIONSITECONFIG 表

OID LOCATIONDETAILOID   SITENAME
1       2               TEST
2       1               NEWTEST

以上查询返回 全球 , NORTH, NORTH1, SOUTH, SOUTH1 NORTH(TEST) AND NORTH1 (重复记录)

我希望查询返回 全球 , NORTH (TEST), NORTH1, SOUTH, SOUTH1

如果孩子已经创建了站点,则查询应该忽略。请帮忙

【问题讨论】:

  • 您是否要返回 GLOBAL (NEWTEST)、NORTH (TEST)、NORTH1、SOUTH、SOUTH1?

标签: sql-server tsql sql-server-2012 recursive-cte


【解决方案1】:

通过将您的 CTE 更改为以 GLOBAL 作为锚成员开始。需要调整递归部分以包含 SITENAME,这是通过合并(如果位置没有站点名称)和子查询来完成的。

with LOCALSITEHIERARCHY
     as (
     select A.OID
          , A.PARENTOID
          , cast(A.LOCATIONNAME+' ( '+LSC.SITENAME+' )' as nvarchar(100)) as NAME
          , LSC.OID as SITEOID
          , cast(row_number() over(partition by parentoid order by A.LOCATIONNAME) as varchar(max)) as [PATH]
     from LOCATIONDETAIL as A
          inner join LOCATIONSITECONFIG as LSC on LSC.LOCATIONDETAILOID = A.OID
     where 1 = 1
           and A.PARENTOID is null
           and LSC.RECSTATUS = 'A'
     union all
     select A.OID
          , A.PARENTOID
          , cast(coalesce(A.LOCATIONNAME+' ( '+
                         (
                             select SITENAME
                             from LOCATIONSITECONFIG C
                             where C.LOCATIONDETAILOID = A.OID
                         )+' )', A.LOCATIONNAME) as nvarchar(100)) as NAME
          , coalesce((select C.OID from LOCATIONSITECONFIG C where C.LOCATIONDETAILOID = A.OID),NULL) as SITEOID
          , [path]+'-'+cast(row_number() over(partition by A.parentoid order by A.LOCATIONNAME) as varchar(max))
     from LOCATIONDETAIL as A
          inner join LOCALSITEHIERARCHY as LH on A.PARENTOID = LH.OID)

     select * from LOCALSITEHIERARCHY order by [PATH];

生成的输出如下图所示。

【讨论】:

  • 感谢 Koen,精心起草的答案。让我试着回复你。
  • 我尝试了解决方案。 SiteOID 应该相应地显示,这里它是 LOCATIONSITECONFIG 中的最后一个 OID 正在重复。我想让 NORTH(Test) 将 siteoid 设为 1,将 Global (NewTEST) 设为 2。请您帮忙。
  • 所以你的意思是第四列SITEOID应该是1、2、NULL、NULL、NULL?如果位置存在站点名称,则仅显示 siteoid?
猜你喜欢
  • 2014-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-14
  • 2011-10-02
  • 1970-01-01
  • 2013-11-03
相关资源
最近更新 更多