Forum Discussion
frankno1105
Sep 09, 2024Copper Contributor
Make Organization
I have a table with organizational structure. It has an ID column called ID. The table also has a column called MOTHER_ID. This refers to the level (MOR) above in the organizational structure. It als...
- Sep 10, 2024
My implementation is a bit complicated:
- Use recursive CTE to flat all mother nodes, it constructs a result set named C1.
- Use recursive CTE again to flat all child nodes, build a result set named C2. Now it has (node count) * (total level) = 8 * 6= 48 rows, all flated rows are there.
- Then you can use any method you like to query out the final result.
- I used PIVOT twice to get ID set and Name set, then JOIN them, That's it.
Here is code with sample data
--Build test table CREATE TABLE #Organize ( ID varchar(20), Name varchar(20), Mother_ID varchar(20), Level int ) GO --Fill test Data, same as the sample INSERT INTO #Organize VALUES ('10020027', 'Level 1 name', NULL, 1) ,('10020028', 'Level 2 name', '10020027', 2) ,('10020032', 'Level 3 name', '10020028', 3) ,('10020035', 'Level 4 name', '10020032', 4) ,('10020166', 'Level 5 name', '10020035', 5) ,('10020038', 'Level 6 name', '10020166', 6) ,('10020083', 'Level 3 name', '10020028', 3) ,('10020188', 'Level 4 name', '10020083', 4) GO WITH C1(ID, Name, Mother_ID, Level, Last_Child_ID) --First CTE, Flat mother nodes AS ( SELECT ID, Name, Mother_ID, Level, ID AS Last_Child_ID FROM #Organize UNION ALL SELECT O.ID, O.Name, O.Mother_ID, O.Level, C1.Last_Child_ID FROM #Organize O INNER JOIN C1 ON C1.Mother_ID = O.ID ) , C2(ID, Name, Mother_ID, Level, Last_Child_ID) --2nd CTE, Flat child nodes AS ( SELECT ID, Name, Mother_ID, Level, Last_Child_ID FROM C1 UNION ALL SELECT C2.ID, C2.Name, C2.ID AS Mother_ID, C2.Level+1 AS Level, C2.Last_Child_ID FROM C2 WHERE C2.ID = C2.Last_Child_ID AND C2.Level+1 <=6 ) SELECT P.Last_Child_ID AS [Org_ID] --Get result ,P.[1] AS [Level 1 ID], N.[1] AS [Level 1 Name] ,P.[2] AS [Level 2 ID], N.[2] AS [Level 2 Name] ,P.[3] AS [Level 3 ID], N.[3] AS [Level 3 Name] ,P.[4] AS [Level 4 ID], N.[4] AS [Level 4 Name] ,P.[5] AS [Level 5 ID], N.[5] AS [Level 5 Name] ,P.[6] AS [Level 6 ID], N.[6] AS [Level 6 Name] FROM ( SELECT Last_Child_ID, Level, ID FROM C2 ) AS SR PIVOT --Get IDs ( MAX(ID) FOR Level IN ([1],[2],[3],[4],[5],[6]) )AS P INNER JOIN (SELECT N.Last_Child_ID ,[1] ,[2] ,[3] ,[4] ,[5] ,[6] FROM ( SELECT Last_Child_ID, Level, Name FROM C2 ) AS SR PIVOT --Get Names ( MAX(Name) FOR Level IN ([1],[2],[3],[4],[5],[6]) )AS N)N ON P.Last_Child_ID = N.Last_Child_ID ORDER BY Org_ID --Drop test table DROP TABLE #OrganizeResult is here
rodgerkong
Sep 10, 2024Iron Contributor
Try use PIVOT? Recured CTE is difficult fill multiple columns with one column source.
frankno1105
Sep 10, 2024Copper Contributor
rodgerkong Want PIVOT only "move" the columns? I also want to make it fill the levels both above and below the level that are existing.
- rodgerkongSep 10, 2024Iron Contributor
My implementation is a bit complicated:
- Use recursive CTE to flat all mother nodes, it constructs a result set named C1.
- Use recursive CTE again to flat all child nodes, build a result set named C2. Now it has (node count) * (total level) = 8 * 6= 48 rows, all flated rows are there.
- Then you can use any method you like to query out the final result.
- I used PIVOT twice to get ID set and Name set, then JOIN them, That's it.
Here is code with sample data
--Build test table CREATE TABLE #Organize ( ID varchar(20), Name varchar(20), Mother_ID varchar(20), Level int ) GO --Fill test Data, same as the sample INSERT INTO #Organize VALUES ('10020027', 'Level 1 name', NULL, 1) ,('10020028', 'Level 2 name', '10020027', 2) ,('10020032', 'Level 3 name', '10020028', 3) ,('10020035', 'Level 4 name', '10020032', 4) ,('10020166', 'Level 5 name', '10020035', 5) ,('10020038', 'Level 6 name', '10020166', 6) ,('10020083', 'Level 3 name', '10020028', 3) ,('10020188', 'Level 4 name', '10020083', 4) GO WITH C1(ID, Name, Mother_ID, Level, Last_Child_ID) --First CTE, Flat mother nodes AS ( SELECT ID, Name, Mother_ID, Level, ID AS Last_Child_ID FROM #Organize UNION ALL SELECT O.ID, O.Name, O.Mother_ID, O.Level, C1.Last_Child_ID FROM #Organize O INNER JOIN C1 ON C1.Mother_ID = O.ID ) , C2(ID, Name, Mother_ID, Level, Last_Child_ID) --2nd CTE, Flat child nodes AS ( SELECT ID, Name, Mother_ID, Level, Last_Child_ID FROM C1 UNION ALL SELECT C2.ID, C2.Name, C2.ID AS Mother_ID, C2.Level+1 AS Level, C2.Last_Child_ID FROM C2 WHERE C2.ID = C2.Last_Child_ID AND C2.Level+1 <=6 ) SELECT P.Last_Child_ID AS [Org_ID] --Get result ,P.[1] AS [Level 1 ID], N.[1] AS [Level 1 Name] ,P.[2] AS [Level 2 ID], N.[2] AS [Level 2 Name] ,P.[3] AS [Level 3 ID], N.[3] AS [Level 3 Name] ,P.[4] AS [Level 4 ID], N.[4] AS [Level 4 Name] ,P.[5] AS [Level 5 ID], N.[5] AS [Level 5 Name] ,P.[6] AS [Level 6 ID], N.[6] AS [Level 6 Name] FROM ( SELECT Last_Child_ID, Level, ID FROM C2 ) AS SR PIVOT --Get IDs ( MAX(ID) FOR Level IN ([1],[2],[3],[4],[5],[6]) )AS P INNER JOIN (SELECT N.Last_Child_ID ,[1] ,[2] ,[3] ,[4] ,[5] ,[6] FROM ( SELECT Last_Child_ID, Level, Name FROM C2 ) AS SR PIVOT --Get Names ( MAX(Name) FOR Level IN ([1],[2],[3],[4],[5],[6]) )AS N)N ON P.Last_Child_ID = N.Last_Child_ID ORDER BY Org_ID --Drop test table DROP TABLE #OrganizeResult is here
- frankno1105Sep 11, 2024Copper ContributorThis worked perfectly! Thank you