Nick
Nick

Reputation: 234

CTE to build hierarchy from source table

I am trying to build a CTE or just some query that takes hierarchial data from one table and insert it into another table that might have a different index. I thought this would be simple, but for some reason I'm getting stuck. I can't get the output to read correctly on the 'RequiredID' with the newly seeded index. Btw I'm working in SQL Server 2012.

Below I've provided proof of concept code to demonstrate what I'm going for. The actual SQL is more complex, but this illustrates the point.

This is what I've got so far:

DECLARE @Table TABLE (ID INT, Code NVARCHAR(50), RequiredID INT);

INSERT INTO @Table (ID, Code, RequiredID)   VALUES
    (1, 'Physics', NULL),
    (2, 'Advanced Physics', 1),
    (3, 'Nuke', 2),
    (4, 'Health', NULL);    

DECLARE @DefaultSeed TABLE (ID INT, Code NVARCHAR(50), RequiredID INT);

WITH hierarchy 
AS (
    --anchor
    SELECT  t.ID , t.Code , t.RequiredID
    FROM @Table AS t
    WHERE t.RequiredID IS NULL

    UNION ALL   

    --recursive
    SELECT  t.ID 
          , t.Code 
          , h.ID        
    FROM hierarchy AS h
        JOIN @Table AS t 
            ON t.RequiredID = h.ID
    )

INSERT INTO @DefaultSeed (ID, Code, RequiredID)
SELECT  ID 
        , Code 
        , RequiredID
FROM hierarchy
OPTION (MAXRECURSION 10)


DECLARE @NewSeed TABLE (ID INT IDENTITY(10, 1), Code NVARCHAR(50), RequiredID INT)

--this is where I get stuck - I can't get the requiredID to read like below
INSERT INTO @NewSeed (Code, RequiredID)
SELECT  Code, RequiredID 
FROM @DefaultSeed

--I'm trying to get @NewSeed should read like the following...
[ID]  [Code]           [RequiredID]
10....Physics..........NULL
11....Health...........NULL
12....AdvancedPhysics..10
13....Nuke.............12


SELECT *
FROM @NewSeed

Any help would be greatly appreciated!

Upvotes: 2

Views: 219

Answers (1)

bummi
bummi

Reputation: 27377

You can use OUTPUT in combination with Merge to get a Mapping from ID's to new ID's.

The essential part:

--this is where you got stuck
Declare @MapIds Table (aOldID int,aNewID int)

;MERGE INTO @NewSeed AS TargetTable
Using @DefaultSeed as Source on 1=0
WHEN NOT MATCHED then
 Insert (Code,RequiredID)
 Values
 (Source.Code,Source.RequiredID)
OUTPUT Source.ID ,inserted.ID into @MapIds;


Update @NewSeed Set RequiredID=aNewID
from @MapIds
Where RequiredID=aOldID

and the whole example:

DECLARE @Table TABLE (ID INT, Code NVARCHAR(50), RequiredID INT);

INSERT INTO @Table (ID, Code, RequiredID)   VALUES
    (1, 'Physics', NULL),
    (2, 'Advanced Physics', 1),
    (3, 'Nuke', 2),
    (4, 'Health', NULL);    

DECLARE @DefaultSeed TABLE (ID INT, Code NVARCHAR(50), RequiredID INT);

WITH hierarchy 
AS (
    --anchor
    SELECT  t.ID , t.Code , t.RequiredID
    FROM @Table AS t
    WHERE t.RequiredID IS NULL

    UNION ALL   

    --recursive
    SELECT  t.ID 
          , t.Code 
          , h.ID        
    FROM hierarchy AS h
        JOIN @Table AS t 
            ON t.RequiredID = h.ID
    )

INSERT INTO @DefaultSeed (ID, Code, RequiredID)
SELECT  ID 
        , Code 
        , RequiredID
FROM hierarchy
OPTION (MAXRECURSION 10)


DECLARE @NewSeed TABLE (ID INT IDENTITY(10, 1), Code NVARCHAR(50), RequiredID INT)

Declare @MapIds Table (aOldID int,aNewID int)

;MERGE INTO @NewSeed AS TargetTable
Using @DefaultSeed as Source on 1=0
WHEN NOT MATCHED then
 Insert (Code,RequiredID)
 Values
 (Source.Code,Source.RequiredID)
OUTPUT Source.ID ,inserted.ID into @MapIds;


Update @NewSeed Set RequiredID=aNewID
from @MapIds
Where RequiredID=aOldID


/*
--@NewSeed should read like the following...
[ID]  [Code]           [RequiredID]
10....Physics..........NULL
11....Health...........NULL
12....AdvancedPhysics..10
13....Nuke.............12
*/

SELECT *
FROM @NewSeed

Upvotes: 2

Related Questions