如何在相邻列表中复制节点的子节点

时间:2013-07-26 10:55:07

标签: sql-server

我有一个构成主题结构的相邻列表层次结构模型

   ID   Parent_Id Topic_Name
   1    Null      Topic 1
   2    Null      Topic 2
   3    2            Topic 3
   4    3               Topic 4
   5    2            Topic 5
   6    Null      Topic 6

我想指定一个主题ID,然后将其复制到某个位置的新主题ID并保留下面的级别/结构

所以在我的例子中,我可以用pos_id 1指定主题topic_id 2,它会创建

   ID   Parent_Id Topic_Name
   1    Null      Topic 1
   7    Null      Topic 2
   8    7            Topic 3
   9    8               Topic 4
   10    7            Topic 5
   2    Null      Topic 2
   3    2            Topic 3
   4    3               Topic 4
   5    2            Topic 5
   6    Null      Topic 6

topic_id是要复制的节点,pos_id是在

之后插入副本的节点

ID已启用自动编号,但我无法保证子节点始终是父节点的下一个ID号。

topic_id是要复制的节点,pos_id是在

之后插入副本的节点

2 个答案:

答案 0 :(得分:1)

你可能想看一下嵌套树集,我认为这对你的目的更好。

这里有很好的解释:

http://en.wikipedia.org/wiki/Nested_set_model

答案 1 :(得分:1)

我认为你可以在一个声明中做到这一点。这是想法。

首先,为每个id扩展所有父级(无论级别)的数据。这使用递归CTE。

然后,返回原始列表,只选择那些2的后代。

然后为此组中找到的每个ID分配一个新ID。以下查询获取该最大ID并向其添加row_number()常量。

然后,对于子树中的每条记录,在记录中查找新的id,然后插入结果。

以下查询采用此方法。我没有测试过它:

with Parents as (
      select id, parent_id, 1 as level
      from AdjList al
      union all
      select cte.id, cte.Parent_id, level+1
      from AdjList al join
           cte
           on cte.Parent_id = al.id
     ),
     LookingFor as (
      select *
      from AdjList
      where id in (select id from Parents where id = 2)
     ),
     NewIds as (
      select id, const.maxid + ROW_NUMBER() over (order by (select NULL)) as newid
      from (select distinct id
            from LookingFor
           ) t cross join
           (select MAX(id) as maxid, from AdjList) const
     )
insert into AdjList(Id, Parent_id, Topic_Name)
    select ni1.newid, coalesce(ni2.NEWID, 1), lf.Topic_Name
    from LookingFor lf left outer join
         NewIds ni1
         on lf.id = ni1.id left outer join
         NewIds ni2
         on lf.Parent_Id = ni2.id
    where ni1.newid is not null