Sql server 合并父子行-TSQL

Sql server 合并父子行-TSQL,sql-server,tsql,parent-child,Sql Server,Tsql,Parent Child,我正在尝试将具有父子层次结构的表中的行展平/合并。我试图识别每个“链接”的开始和结束-因此,如果a链接到b,b链接到c,然后c链接到d,我希望输出链接到a到d 我正在尽我最大的努力避免使用带有循环的过程,因此任何建议都将不胜感激 原始数据集和所需输出如下: personID | form | linkedform ---------|---------|--------- 1 | a | b 1 | b | c 1

我正在尝试将具有父子层次结构的表中的行展平/合并。我试图识别每个“链接”的开始和结束-因此,如果a链接到bb链接到c,然后c链接到d,我希望输出链接到ad

我正在尽我最大的努力避免使用带有循环的过程,因此任何建议都将不胜感激

原始数据集和所需输出如下:

personID | form    | linkedform   
---------|---------|---------
    1    |    a    |   b
    1    |    b    |   c
    1    |    c    |   d
    1    |    d    |   NULL
    2    |    e    |   f
    2    |    f    |   g
    2    |    g    |   NULL
    2    |    h    |   i
    2    |    i    |   NULL
    3    |    j    |   NULL
    3    |    k    |   l
    3    |    l    |   NULL
期望输出:

personID | form    | linkedform   
---------|---------|---------
    1    |    a    |   d
    2    |    e    |   g
    2    |    h    |   i
    3    |    j    |   NULL
    3    |    k    |   l

每个personID可以有多个链接,一个链接可以由一个或多个表单组成

这看起来像是一个使用max函数的简单groupby。编辑:再想一想,也许不是……在我看来,您希望每个人都有所有形式的叶节点,这是通过tSQL中的递归CTE处理的@我不这么认为。看看Personid3或Personid2,其中存在多条路径。从这里开始,期望的输出只有几步之遥。路径总是线性的,还是可以分支出一些?我的意思是,可以直接链接到b和c,并且从那里有多个端点吗?非常感谢你的评论(以及有用的额外评论)。非常感谢!
-- use a recursive cte to build the hierarchy
-- start with [linkedform] = null and work your way up
;WITH cte AS 
(
    SELECT  *, [form] AS [root],
            1 AS [Level]
    FROM    Table1
    WHERE   [linkedform] IS NULL
    UNION ALL  
    SELECT  t1.*,
            [root],
            [Level] + 1
    FROM    Table1 t1
    JOIN    cte ON cte.form = t1.linkedform
)
-- level 1 will be the last element, use row_number to get the first element
-- join the two together based on last and first level, that have the same personid and root ([linkedform] = null)
SELECT  cte.personId,
        cte2.form, 
        cte.form
FROM    cte
        JOIN (  SELECT  *, 
                        ROW_NUMBER() OVER (PARTITION BY personId, [root] ORDER BY Level DESC) Rn 
                FROM    cte) cte2 
            ON cte2.Rn = cte.Level 
                AND cte2.personId = cte.personId
                AND cte2.root = cte.root
WHERE   cte.[Level] = 1
ORDER BY cte.personId, cte2.form