递归CTE SQL(父子)

时间:2017-08-16 14:45:42

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

我正在使用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纳入全球网站。

示例,添加名为(NEWTEST)的站点2,即全局

LOCATIONSITECONFIG表

OID LOCATIONDETAILOID   SITENAME
1       2               TEST
2       1               NEWTEST

上面的Query返回             全球,北,NORTH1,南,南1             再次北(测试)和NORTH1(记录重复)

我希望查询返回             全球,北(测试),NORTH1,SOUTH,SOUTH1

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

1 个答案:

答案 0 :(得分:0)

通过将您的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];

结果输出如下图所示。

Result from Query