You don't need to use a loop ...
Have a look at this recursive Common Table Expression
;WITH usr_CTE AS (
SELECT UserID, ParentID,[Name]
, 1 as RLevel
, MtoE = CAST(isnull(ParentID,0) AS VARCHAR(MAX)) + '/' +
CAST(UserID AS VARCHAR(MAX))
FROM [Users]
WHERE ParentID IS NULL
UNION ALL
SELECT e.UserID, e.ParentID, e.[Name]
, RLevel + 1
, MtoE = MtoE + '/' + CAST(e.UserID AS VARCHAR(MAX))
FROM [Users] e
INNER JOIN usr_CTE ecte ON ecte.UserID = e.ParentID
)
SELECT UserID, EC.ParentID, [Name], RLevel, MtoE
FROM usr_CTE EC
With my dummy data that I set up (a cut down version of Northwind database's Employee table) I get the following results
UserId Parent Name Level Path to Node
2 NULL Andrew Fuller 1 0/2
1 2 Nancy Davolio 2 0/2/1
3 2 Janet Leverling 2 0/2/3
4 2 Margaret Peacock 2 0/2/4
5 2 Steven Buchanan 2 0/2/5
8 2 Laura Callahan 2 0/2/8
6 5 Michael Suyama 3 0/2/5/6
7 5 Robert King 3 0/2/5/7
9 5 Anne Dodsworth 3 0/2/5/9
(Where I have searched for
ParentID IS NULL
is where you would use
ParentID in (@NodeFor)
So to get the number of children at each level you just change the final select from the CTE:
;WITH usr_CTE AS (
SELECT UserID, ParentID,[Name], 1 as RLevel
FROM [Users]
WHERE ParentID IS NULL
UNION ALL
SELECT e.UserID, e.ParentID, e.[Name], RLevel + 1
FROM [Users] e
INNER JOIN usr_CTE ecte ON ecte.UserID = e.ParentID
)
SELECT RLevel, COUNT(*)
FROM usr_CTE EC
GROUP BY RLevel
which gave me
Level Count
1 1
2 5
3 3
Caveat:
Depending on the volume of data in your table you may get an error
Quote:
“Msg 530, Level 16, State 1, Line 1
The statement terminated. The maximum recursion 100 has been exhausted before statement completion.”
To get around this you can use something like
OPTION (MAXRECURSION 150)
(or however many records you have in your table) That line goes after the GROUP BY clause. Once you are happy that your query is working properly then you can change that to
OPTION (MAXRECURSION 0)