层次结构 - 叶级数据

时间:2018-04-11 17:35:28

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

代码:

CREATE TABLE #Temp ( ID INT, BranchID_New INT, BranchID_Old INT, DateCreated DATETIME2, PRIMARY KEY ( [ID], [BranchID_New], [BranchID_Old] ) ) ;

INSERT INTO #Temp
SELECT  1, 1, 1, '2018-04-11 00:00:00.0000000'
UNION ALL
SELECT 1, 2, 2, '2018-04-11 00:00:00.0000000'
UNION ALL
SELECT 1, 3, 3, '2018-04-11 00:00:00.0000000'
UNION ALL
SELECT 1, 4, 1, '2018-04-11 12:00:00.0000000'   -- BranchID_New 1 and 2 were combined to BranchID_New 4
UNION ALL
SELECT 1, 4, 2, '2018-04-11 12:00:00.0000000'   -- BranchID_New 1 and 2 were combined to BranchID_New 4
UNION ALL
SELECT 1, 4, 4, '2018-04-11 12:00:00.0000000'   -- Also, BranchID_New 4 has its own record as well
UNION ALL
SELECT 1, 5, 5, '2018-04-11 14:00:00.0000000'
UNION ALL
SELECT 1, 6, 3, '2018-04-11 16:00:00.0000000'   -- BranchID_New 3 and 4 (newly combined) were combined to BranchID_New 6
UNION ALL
SELECT 1, 6, 4, '2018-04-11 16:00:00.0000000'   -- BranchID_New 3 and 4 (newly combined) were combined to BranchID_New 6
UNION ALL
SELECT 1, 6, 6, '2018-04-11 16:00:00.0000000'   -- Also, BranchID_New 6 has its own record as well
UNION ALL
SELECT 2, 7, 7, '2018-04-12 00:00:00.0000000'
UNION ALL
SELECT 2, 8, 8, '2018-04-11 00:00:00.0000000'
UNION ALL
SELECT 2, 9, 9, '2018-04-11 00:00:00.0000000'
UNION ALL
SELECT 2, 10, 8, '2018-04-11 12:00:00.0000000'  -- BranchID_New 8 and 9 were combined to BranchID_New 10
UNION ALL
SELECT 2, 10, 9, '2018-04-11 12:00:00.0000000'  -- BranchID_New 8 and 9 were combined to BranchID_New 10
UNION ALL
SELECT 2, 10, 10, '2018-04-11 12:00:00.0000000' -- Also, BranchID_New 10 has its own record as well
UNION ALL
SELECT 3, 11, 11, '2018-04-12 00:00:00.0000000'
UNION ALL
SELECT 3, 12, 12, '2018-04-12 00:00:00.0000000'
UNION ALL
SELECT 3, 13, 13, '2018-04-12 00:00:00.0000000'

SELECT * 
FROM #Temp ;

DROP TABLE #Temp ;

目标: BranchID_Old组合成BranchID_New。然后他们可以进一步组合成更新的BranchID_New。对于每个BranchID_Old,我想找到最新的BranchID_New。另外,我想找到每个BranchID_Old的分层路径。

期望的输出:

ID  BranchID_New    BranchID_Old    DateCreated                 New_BranchID_New    New_BranchID_New_Path
1   1               1               2018-04-11 00:00:00.000     6                   1/4/6/                  
1   2               2               2018-04-11 00:00:00.000     6                   2/4/6/
1   3               3               2018-04-11 00:00:00.000     6                   3/6/
1   4               1               2018-04-11 12:00:00.000     6                   4/6/
1   4               2               2018-04-11 12:00:00.000     6                   4/6/
1   4               4               2018-04-11 12:00:00.000     6                   4/6/
1   5               5               2018-04-11 14:00:00.000     5                   5/
1   6               3               2018-04-11 16:00:00.000     6                   6/
1   6               4               2018-04-11 16:00:00.000     6                   6/
1   6               6               2018-04-11 16:00:00.000     6                   6/
2   7               7               2018-04-12 00:00:00.000     7                   7/
2   8               8               2018-04-11 00:00:00.000     10                  8/10/
2   9               9               2018-04-11 00:00:00.000     10                  9/10/
2   10              8               2018-04-11 12:00:00.000     10                  10/
2   10              9               2018-04-11 12:00:00.000     10                  10/
2   10              10              2018-04-11 12:00:00.000     10                  10/
3   11              11              2018-04-12 00:00:00.000     11                  11/
3   12              12              2018-04-12 00:00:00.000     12                  12/
3   13              13              2018-04-12 00:00:00.000     13                  13/

2 个答案:

答案 0 :(得分:1)

对于层次结构,您可以使用递归cte。根据您的方案,您将排除层次结构的中间部分,如路径1/4。

见下面的代码。

;With cte AS
(--we start with all records 
select [ID], [BranchID_New], [BranchID_Old],DateCreated,[BranchID_New] as [New_BranchID_New],cast('' as varchar(max)) as BranchPath 
from #Temp
UNION ALL
select c.[ID],c.[BranchID_New], c.BranchID_Old,c.DateCreated,t.BranchID_New as New_BranchID_New
,c.BranchPath+cast(c.New_BranchID_New as varchar(max))+'/'--we add the child's newest to the path, which means we will need to add then most new later.
from #Temp t
join cte c on c.New_BranchID_New=t.BranchID_Old and c.ID=t.ID
WHERE c.New_BranchID_New<>t.BranchID_New  --we avoid recusion over parents with the same parent
)
select [ID], [BranchID_New], [BranchID_Old],New_BranchID_New, DateCreated,BranchPath
into #NewBranches
from cte

--we need to remove all the lower hierarchy records, so we will delete them from the results
delete nb1
from #NewBranches nb1
join #NewBranches nb2 on nb1.ID=nb2.ID and nb1.BranchID_New=nb2.BranchID_New and nb1.BranchID_Old=nb2.BranchID_Old and nb1.DateCreated=nb2.DateCreated
where nb1.BranchPath<nb2.BranchPath

--we create the path based on hierarchy and add the BranchID_Newest
select ID, BranchID_New,BranchID_Old,DateCreated,New_BranchID_New as New_BranchID_New
,case when BranchID_New=New_BranchID_New then ''--current record is the newest
when BranchID_New<>New_BranchID_New then ''+BranchPath--keep path
end +cast(New_BranchID_New as varchar(max))+'/'
 as New_BranchID_New_Path
 from #NewBranches
 order by 1,2,3

答案 1 :(得分:1)

你需要递归。这是一个选项

with rcte as (
    select
        *, New_BranchID_New = BranchID_New, step = 1, DateCreated_New = DateCreated
        , New_BranchID_New_Path = cast(concat(BranchID_New, '/') as varchar(2000))
    from 
        #Temp
    union all
    select
        a.ID, a.BranchID_New, a.BranchID_Old, a.DateCreated, b.BranchID_New, step + 1
        , b.DateCreated, cast(concat(a.New_BranchID_New_Path, b.BranchID_New, '/') as varchar(2000))
    from
        rcte a
        join #Temp b on a.New_BranchID_New = b.BranchID_Old 
                        and b.BranchID_New <> b.BranchID_Old 
                        and a.DateCreated_New < b.DateCreated
)

select
    ID, BranchID_New, BranchID_Old, DateCreated, New_BranchID_New, New_BranchID_New_Path
from (
    select
        ID, BranchID_New, BranchID_Old, DateCreated, New_BranchID_New, New_BranchID_New_Path
        , rn = row_number() over (partition by ID, BranchID_New, BranchID_Old, DateCreated order by step desc)
    from 
        rcte
) t
where
    rn = 1

输出

ID  BranchID_New BranchID_Old DateCreated                   New_BranchID_New New_BranchID_New_Path
--------------------------------------------------------------------------------------------------
1   1            1            2018-04-11 00:00:00.0000000   6                1/4/6/
1   2            2            2018-04-11 00:00:00.0000000   6                2/4/6/
1   3            3            2018-04-11 00:00:00.0000000   6                3/6/
1   4            1            2018-04-11 12:00:00.0000000   6                4/6/
1   4            2            2018-04-11 12:00:00.0000000   6                4/6/
1   4            4            2018-04-11 12:00:00.0000000   6                4/6/
1   5            5            2018-04-11 14:00:00.0000000   5                5/
1   6            3            2018-04-11 16:00:00.0000000   6                6/
1   6            4            2018-04-11 16:00:00.0000000   6                6/
1   6            6            2018-04-11 16:00:00.0000000   6                6/
2   7            7            2018-04-12 00:00:00.0000000   7                7/
2   8            8            2018-04-11 00:00:00.0000000   10               8/10/
2   9            9            2018-04-11 00:00:00.0000000   10               9/10/
2   10           8            2018-04-11 12:00:00.0000000   10               10/
2   10           9            2018-04-11 12:00:00.0000000   10               10/
2   10           10           2018-04-11 12:00:00.0000000   10               10/
3   11           11           2018-04-12 00:00:00.0000000   11               11/
3   12           12           2018-04-12 00:00:00.0000000   12               12/
3   13           13           2018-04-12 00:00:00.0000000   13               13/