1

トピック構造を構成する隣接リスト階層モデルがあります

   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にコピーして、その下のレベル/構造を保持したい

したがって、私の例では、トピックtopic_id 2を指定すると、次のようになります。

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

IDは自動番号付けで処理されるため、それを作成する必要はありませんが、明らかに親IDを保持する必要があります

どうすれば上記を達成できますか?データをフラット化し、各挿入後にIDをログに記録する3つの別々の挿入を行う必要がありますか?

4

2 に答える 2

2

再帰CTEを使用して、挿入する行を取得できます。merge行を追加するために使用する場合は、生成されたIDと、挿入された行の列を更新するために使用できる古いIDとの間のマッピングoutputをキャプチャするために使用できます。Parent_ID

-- ID for topic to copy 
declare @ID int;
set @ID = 2;

-- Table to hold the inserted rows
declare @T table
(
  New_ID int,
  Old_ID int,
  Old_ParentID int
);

-- Add rows from recursive CTE using merge
with C as
(
  select T.ID, T.Parent_Id, T.Topic_Name
  from YourTable as T
  where T.ID = @ID
  union all
  select T.ID, T.Parent_Id, T.Topic_Name
  from YourTable as T
    inner join C 
      on C.ID = T.Parent_Id
)
merge YourTable
using C
on 0 = 1
when not matched then
  insert (Topic_Name) values (C.Topic_Name)
output inserted.ID,
       C.ID,
       C.Parent_Id
  into @T(New_ID, Old_ID, Old_ParentID);

-- Update Parent_Id for the new rows
update Y set
  Parent_Id = T2.New_ID
from @T as T1
  inner join @T as T2
    on T1.Old_ParentID = T2.Old_ID
  inner join YourTable as Y
    on T1.New_ID = Y.ID;

SE-データ

于 2012-10-03T11:53:28.293 に答える
1

実例。理論的には機能しますが、トランザクション量が多い場合や大きなテーブルの場合は十分に高速ではない可能性があります。

--- sample table
create table tbl (
  id int identity primary key,
  parent_id int references tbl(id),
  topic_name varchar(100));
insert tbl values
(       Null,  'Topic 1'),
(       1,  '   Topic 2'),
(       2   ,  '       Topic 3'),
(       3   ,  '          Topic 4'),
(       2   ,  '       Topic 5'),
(       Null,  '    Topic 6'),
(       4,  '    Topic 4-3'),
(       7,  '    Topic 5-4')
;

--- script to duplicate a hierarchy branch
declare @inserttbl table (
  id int,
  parent_id int,
  topic_name varchar(100));
;with cte as (
  select id, parent_id, topic_name
  from tbl
  where id=2 -- or parameter
  union all
  select t.id, t.parent_id, t.topic_name
  from tbl t
  join cte c on t.parent_id=c.id
), cte2 as (
  select *,rn=row_number() over (order by id)
  from cte
), cte3 as (
  select rec.*, par.rn as parent_rn
  from cte2 rec
  left join cte2 par on par.id=rec.parent_id
)
insert @inserttbl
select cte3.rn,
       case when cte3.rn=1 then cte3.parent_id
            else cte3.parent_rn end,
       topic_name
from cte3;

insert tbl(topic_name)
select topic_name from @inserttbl order by id;

declare @delta int=scope_identity()-@@rowcount;

update t
set parent_id = i.parent_id + case when i.id=1 then 0
                              else @delta end
from tbl t
join @inserttbl i on t.id - @delta = i.id;

--- check results
select * from tbl;
于 2012-10-03T11:09:52.613 に答える