I have a basic recursive table setup in SQL 2008 with the following structure:
CREATE TABLE [dbo].[Employee]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
[ManagerId] [int] NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED ([Id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[Employee] WITH CHECK ADD CONSTRAINT [FK_Employee_Employee] FOREIGN KEY([ManagerId]) REFERENCES [dbo].[Employee] ([Id])
Based on a couple of different articles online, I found where I can write a query such as the following to return a “manager” and all child records contained underneath:
WITH DirectRelationships AS
(
SELECT Id, Name, ManagerId, Depth = 0
FROM Employee
WHERE ManagerId = 1
UNION ALL
SELECT e.Id, e.Name, e.ManagerId, Depth = Depth + 1
FROM Employee e
INNER JOIN DirectRelationships DR ON DR.Id = e.ManagerId
WHERE Depth <= 2 /* this doesn't work */
)
SELECT * FROM DirectRelationships
When I run the select statement above without the “WHERE Depth <= 2” I get four columns back (Id, Name, ManagerId, Depth) that show the exact records I am looking for. The problem I run into is Depth is based on the overall depth from the root record (where ManagerId is null) and not the depth the record is from the requested manager.
For instance, assume I have the following data in this table:
select * from Employee;
Id | Name | ManagerId | Depth
------------------------------------------
1 CEO 0 0
2 National Director 1 1
3 Regional Director 2 2
4 Store Director 3 3
5 Clerk 4 4
6 Clerk #2 4 4
What I want my query to be able to do is get a manager level (say, National Director or Id #2) and specify the number of levels to recursively pull (say, 2). That would return the following:
Id | Name | ManagerId | Depth
------------------------------------------
2 National Director 1 0 /*top level requested */
3 Regional Director 2 1 /*new depth based on requested parent */
4 Store Director 3 2 /*new depth based on requested parent */
So I wouldn’t get the top-level CEO position and I also wouldn’t get the individual clerks because I only wanted a specific entry and 2 levels below that. I’ve seen where you can specify MAXRECURSION in a query, but that throws an error if the level exceeds the number you specify which isn’t desirable. The hierarchical structure I’ll be dealing with could have thousands of records and for any specific entity listing I’ll only want up to 5 of the children levels with the others being irrelevant.
Any help would be much appreciated!
Try running:
You should get the result you are looking for: