Sql server CTE获取父级的子级,然后使用父值更新子级

时间:2018-05-14 12:20:08

标签: sql sql-server common-table-expression

如何遍历所有子节点并为所有节点更新一列?例如,如果我在父级别上使用列" OrganisationLevelID"。如果我更新" OrganisationLevelID"在父母行上,它应该传播给孩子,因此父母和孩子的所有孩子都可以。然后,孩子们应该在" OrganisationLevelID"。

中拥有相同的价值

我有以下cte

 WITH cte as
(select h.Name, h.ID, h.OrganisationLevelID, h.parentId
From organisations h
WHERE ID = '3eea8c17-1bfd-46d5-9ea9-2d11652d23a4'
UNION ALL 
select p.Name, p.ID, p.OrganisationLevelID, p.parentId
FROM organisations p
INNER JOIN cte c ON c.Id = p.parentId)
SELECT *  FROM cte

这将获得父子层次结构并正常工作。

如何更新子级值,以便他们都拥有父级" OrganisationLevelID"?

 WITH cte as
    (select h.Name, h.ID, h.OrganisationLevelID, h.parentId
    From organisations h
    WHERE ID = '3eea8c17-1bfd-46d5-9ea9-2d11652d23a4'
    UNION ALL 
    select p.Name, p.ID, p.OrganisationLevelID, p.parentId
    FROM organisations p
    INNER JOIN cte c ON c.Id = p.parentId),
  cteupdate as(**Some magic here**)

1 个答案:

答案 0 :(得分:1)

如果您正在寻找更新Organisations表格中的实际记录,我相信您可以尝试这样做:

;WITH cte
AS (
    SELECT h.Name
        , h.ID
        , h.OrganisationLevelID
        , h.parentId
    FROM organisations h
    WHERE ID = '3eea8c17-1bfd-46d5-9ea9-2d11652d23a4'
    UNION ALL
    SELECT p.Name
        , p.ID
        , c.OrganisationLevelID  -- note that I changed the alias from "p" to "c" to use the parent's value
        , p.parentId
    FROM organisations p
    INNER JOIN cte c
        ON c.Id = p.parentId
    )
UPDATE org
SET OrganisationLevelID = cte.OrganisationLevelID
FROM organisations org
INNER JOIN cte
    ON org.id = cte.id

您可以使用下面的示例代码来查看将会发生什么,特别是来自父行的orgValueId中的值将“传播”到其所有子代和后代:

create table #t (id int, parentid int, orgValueId varchar(10));

insert into #t values (1, null, 'x'), (2, 1, 'o'), (3, 1, 'm'), (4, 2, 'v'), (5, 3, 'p');

select *
from #t;

with cte as (
    select id
        , orgValueId
    from #t
    where parentid is null

    union all

    select t.id
        , c.orgValueId
    from cte c
        inner join #t t on c.id = t.parentid)
update t
    set orgValueId = c.orgValueId 
from #t t
    inner join cte c
        on t.id = c.id;

select *
from #t;