结合父子行 - TSQL

时间:2016-01-05 20:25:37

标签: sql-server tsql parent-child

我正在尝试压缩/组合表中的行与父子层次结构。我试图找出每个链接的开头和结尾。 - 如果 a b 相关联,则 b c 相关联,然后 c < / strong>与 d 相关联,我希望输出将 a 链接到 d

我尽量避免使用带循环的程序,所以任何建议都会非常感激!

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

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可以有多个链接,链接只能由一个或多个表单组成。

1 个答案:

答案 0 :(得分:0)

-- 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