使用SQL克隆数据库中表示的树结构

Amo*_*n17 9 sql t-sql sql-server sql-server-2005

给定一个表示分层树结构并具有三列的表

  1. ID(主键,非自动增量)
  2. ParentGroupID
  3. someValue中

我知道该分支中节点最低的节点,我想将其复制到具有相同数量的父节点的新分支,这些父节点也需要克隆.

我正在尝试编写单个SQL INSERT INTO语句,该语句将使具有相同main的每一行的副本成为新GroupID的第一部分GroupID.

示例开始表:

ID | ParentGroupID | SomeValue
------------------------
1  |      -1       |    a
2  |       1       |    b
3  |       2       |    c
Run Code Online (Sandbox Code Playgroud)

我运行一个简单的INSERT INTO语句后的目标:

ID | ParentGroupID | SomeValue
------------------------
1  |      -1       |    a
2  |       1       |    b
3  |       2       |    c
4  |      -1       |    a-cloned
5  |       4       |    b-cloned
6  |       5       |    c-cloned
Run Code Online (Sandbox Code Playgroud)

最终的树结构

+--a (1)
|  +--b (2)
|     +--c (3)
|
+--a-cloned (4)
|  +--b-cloned (5)
|     +--c-cloned (6)
Run Code Online (Sandbox Code Playgroud)

当这个演示数据显示时,ID并不总是间隔很好,所以我不能总是假设Parent的ID比具有父节点的行的当前ID小1.

此外,我试图在T-SQL(对于Microsoft SQL Server 2005及更高版本)中执行此操作.

这感觉就像一个经典的练习应该有一个纯粹的SQL答案,但我已经习惯了编程,我的思想在关系SQL中没有想到.

Mar*_*ers 3

根据Quassnoi的文章“邻接列表与嵌套集:SQL Server”中的查询尝试一下:

WITH q AS
(
    SELECT  h.*, 1 AS level
    FROM    Table1 h
    WHERE   id = 3
    UNION ALL
    SELECT  hp.*, level + 1
    FROM    q
    JOIN    Table1 hp
    ON      hp.id = q.ParentGroupID
), q2 AS (
    SELECT
        ID,
        ParentGroupID,
        SomeValue,
        (SELECT MAX(level) FROM q) - level AS level
    FROM q
)
INSERT INTO table1
SELECT
    (SELECT MAX(ID) FROM Table1) + level + 1 AS ID,
    CASE WHEN level = 0 THEN -1
         ELSE (SELECT MAX(ID) FROM Table1) + level
    END AS ParentGroupID,
    SomeValue + '-cloned'
FROM    q2
Run Code Online (Sandbox Code Playgroud)

在测试数据上运行时的结果:

ID  ParentGroupID  SomeValue  
1   -1             a          
2   1              b          
3   2              c          
4   -1             a-cloned
5   4              b-cloned
6   5              c-cloned
Run Code Online (Sandbox Code Playgroud)