Reputation: 73
I have this table:
Id ParentId LevelName
1 0 XXXX
2 0 XXXX
4 2 XXXX
5 2 XXXX
6 2 XXXX
7 2 XXXX
8 2 XXXX
9 2 XXXX
18 2 XXXX
19 18 XXXX
20 19 XXXX
I want the top level ParentId from this like. If I will pass the Id 20 then it will return 2, which is the top level Id in the table:
Id ParentId LevelName
2 0 XXXX
My attempt:
WITH cteReports (LvlID, PrntID, LevelID) AS
(SELECT Id,
ParentId,
1
FROM Levels
WHERE Id = @ParentId
UNION ALL
SELECT e.Id,
e.ParentId,
r.LevelID + 1
FROM Levels e
INNER JOIN cteReports r ON e.ParentId = r.LvlID)
SELECT Id
FROM Levels
WHERE Id IN (SELECT LvlID FROM cteReports);
Upvotes: 1
Views: 108
Reputation: 12804
The biggest issue was your join had the tables flipped.
DECLARE @Levels TABLE(
ID INT,
ParentID INT,
LevelName VARCHAR(20)
)
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 1 ,0 ,'XXXX'
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 2 ,0 ,'XXXX'
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 4 ,2 ,'XXXX'
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 5 ,2 ,'XXXX'
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 6 ,2 ,'XXXX'
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 7 ,2 ,'XXXX'
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 8 ,2 ,'XXXX'
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 9 ,2 ,'XXXX'
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 18 ,2 ,'XXXX'
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 19 ,18 ,'XXXX'
INSERT INTO @Levels (ID,ParentID,LevelName) SELECT 20 ,19 ,'XXXX'
DECLARE @TargetID INT=20;
WITH cteReports (Id, ParentId, LevelID) AS
(
SELECT Id,
ParentId,
1
FROM @Levels
WHERE Id = @TargetID
UNION ALL
SELECT e.Id,
e.ParentId,
r.LevelID + 1
FROM @Levels e
INNER JOIN cteReports r ON r.ParentId = e.Id
)
SELECT lvl.*
FROM @Levels lvl
INNER JOIN cteReports cte ON cte.ID=lvl.ID
WHERE LevelID = (
SELECT MAX(LevelID) AS MaxLevelID
FROM cteReports
)
Upvotes: 0
Reputation: 272106
This should do it:
DECLARE @start_id INT = 20;
WITH rcte AS (
SELECT *
FROM t
WHERE id = @start_id
UNION ALL
SELECT curr.*
FROM t AS curr
JOIN rcte AS prev ON curr.id = prev.parentid
)
SELECT *
FROM rcte
WHERE parentid = 0
Upvotes: 3