简体   繁体   中英

How to do loop in SQL Server to merge records

I have records that merge to a merged record in SQL Server. And I am interested to loop through to the top record using sql. The example below makes the question clear.

Tbl_Merge has two columns ChildRecord and ParentRecord :

ChildRecord     ParentRecord
-----------------------------
101             102
102             103
103             104

I want this output:

ChildRecord     ParentRecord
-----------------------------
101             104
102             104
103             104

you can use a recursive CTE. Starts from the record without any child as anchor

; with rcte as
(
    -- anchor member : Parent record
    select  ChildRecord = t.ParentRecord, ParentRecord = NULL, RootRecord = t.ParentRecord
    from    yourtbl t
    where   not exists
            (
                select  *
                from    yourtbl x
                where   x.ChildRecord   = t.ParentRecord
            )

    union all

    -- recursive member
    select  ChildRecord = t.ChildRecord, ParentRecord = t.ParentRecord, RootRecord = r.RootRecord
    from    rcte r
            inner join yourtbl t    on  r.ChildRecord   = t.ParentRecord
)
select  r.ChildRecord, ParentRecord = r.RootRecord
from    rcte r
where   r.ParentRecord  is not null   -- exclude the anchor memmber
create table #temp (ChildRecord int,Parentrecord int)
insert into #temp values(101,102),(102,103),(103,104)


WITH CTE
     AS (SELECT t.ChildRecord,
                t.Parentrecord,
                1 lvl
         FROM #temp t
         UNION ALL
         SELECT c.ChildRecord,
                t.Parentrecord,
                lvl + 1
         FROM #temp t
              INNER JOIN CTE c ON t.ChildRecord = c.Parentrecord),
     CTE2
     AS (SELECT ChildRecord,
                MAX(lvl) maxlvl
         FROM cte
         GROUP BY ChildRecord)
     SELECT c.ChildRecord,
            c.Parentrecord
     FROM cte c
     WHERE EXISTS
     (
         SELECT 1
         FROM cte2 c2
         WHERE c2.maxlvl = c.lvl
               AND c2.ChildRecord = c.ChildRecord
     );
--select * from #temp

DROP TABLE #temp;

Consider the following table:

create table t1 ( child char(3), parent char(3))
go
insert into t1 values ( '101', '102')
insert into t1 values ( '102', '103')
insert into t1 values ( '103', '104')
go

The following query uses a self referential Common Table Expression to navigate over the relationships and build a tree, the table "x". For each child the query finds the maximum depth and returns the child and parent values

with x ( tree, child, parent, depth)
    as
    (
        select
                cast(child as varchar(100)),
                child,
                parent,
                0
            from
                t1
        union all
        select
                cast (x.tree + ':' + t1.child as varchar(100)),
                x.child,
                t1.parent,
                x.depth + 1
            from
                t1,
                x
            where
                x.parent = t1.child
    )
select 
        x1.child,
        x1.parent
    from
        x x1
    where
        x1.depth = 
        (
            select max(x2.depth) from x x2 where x1.child = x2.child
        )
    order by x1.child

Adding the following values, shows this works as expected when the parent has a lower value than the child as well.

insert into t1 values ( '120', '110')
insert into t1 values ( '125', '124')
insert into t1 values ( '124', '123')
insert into t1 values ( '123', '110')
go

Results:

child parent
----- ------
101   104
102   104
103   104
120   110
123   110
124   110
125   110

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM