In this picture, 2018_9UKDT – UKD Expense Total is parent of 2018_9Q400 – UKD Indirects and this in turn is parent to 98064 – IT SDS Costs, 98063 – ACS in charges, 98012 – UKD – Central.
Could someone let me know how to create parent child relation using T-SQL which has upto 10 levels.
Table creation
create table Test
(
ID INT IDENTITY(1,1),
NAME VARCHAR (255),
Level Varchar(25)
);
insert into test (name) values
(' 2018_9UKDT - UKD Expense Total'),
(' 2018_9Q400 - UKD Indirects'),
(' 98064 - IT SDS Costs'),
(' 98063 - ACS in charges'),
(' 98012 - UKD - Central'),
(' 2018_9Q300 - UKD Non Opex Total');
and the output would be in the below attached screen shot. Basically from least level to increasing order.
Advertisement
Answer
Since you know you have a max level of 10, you can use a couple of common table expressions and conditional aggregation:
With CTE1 AS
(
SELECT Id,
name,
DENSE_RANK() OVER(ORDER BY LEN(name) - LEN(LTRIM(name)) DESC) As Level
FROM Test
), CTE2 AS
(
SELECT Id,
Name,
Level,
ISNULL((SELECT MIN(ID)
FROM CTE1 As t1
WHERE T1.Level > T0.Level
), Id) As ParentId
FROM CTE1 As T0
)
SELECT MAX(CASE WHEN Level = 1 THEN Trimmed END) As Level1
,MAX(CASE WHEN Level = 2 THEN Trimmed END) As Level2
,MAX(CASE WHEN Level = 3 THEN Trimmed END) As Level3
,MAX(CASE WHEN Level = 4 THEN Trimmed END) As Level4
-- more of the same
FROM CTE2
CROSS APPLY
(SELECT LTRIM(RTRIM(Name)) As Trimmed) As DRY
GROUP BY ParentId
Results (for the sample data posted on the question):
Level1 Level2 Level3 Level4
98064 - IT SDS Costs 2018_9Q400 - UKD Indirects 2018_9UKDT - UKD Expense Total NULL
Please note that for multiple root nodes, it will be difficult to know where the root node is (basically, you could have Level1
, Level2
… as null, where at least one other node have more children.
Therefor, you should probably have the root node on the left most column. To do that, change the dense_rank
order by from DESC
to ASK
, and the condition on the subquery in the second cte from WHERE T1.Level > T0.Level
to WHERE T1.Level < T0.Level
.