rborda
asked on
SQL Supervisor in a hierarchy
Hi,
Thank you in advance for any feedback.
I have downloaded Adventure works 2012 SQL Database.
I would like to get the supervisor id for an employee, but I don't understand all the heriarchy thing that is being used under organizationNode of HumanResources.Employee table.
Having a procedure that receives an employee id, inside the procedure I would like to be able to
obtain the supervisor's id. Not have all the managers, but the immediate supervisor to an employee.
Thank you in advance for any feedback.
I have downloaded Adventure works 2012 SQL Database.
I would like to get the supervisor id for an employee, but I don't understand all the heriarchy thing that is being used under organizationNode of HumanResources.Employee table.
Having a procedure that receives an employee id, inside the procedure I would like to be able to
obtain the supervisor's id. Not have all the managers, but the immediate supervisor to an employee.
ASKER
How can I modify the following procedure to get the immediate manager only, and not all the managers?
CREATE PROCEDURE [dbo].[uspGetEmployeeManag ers]
@EmployeeID [int]
AS
BEGIN
SET NOCOUNT ON;
-- Use recursive query to list out all Employees required for a particular Manager
WITH [EMP_cte]([EmployeeID], [ManagerID], [FirstName], [LastName], [Title], [RecursionLevel]) -- CTE name and columns
AS (
SELECT e.[EmployeeID], e.[ManagerID], c.[FirstName], c.[LastName], e.[Title], 0 -- Get the initial Employee
FROM [HumanResources].[Employee ] e
INNER JOIN [Person].[Contact] c
ON e.[ContactID] = c.[ContactID]
WHERE e.[EmployeeID] = @EmployeeID
UNION ALL
SELECT e.[EmployeeID], e.[ManagerID], c.[FirstName], c.[LastName], e.[Title], [RecursionLevel] + 1 -- Join recursive member to anchor
FROM [HumanResources].[Employee ] e
INNER JOIN [EMP_cte]
ON e.[EmployeeID] = [EMP_cte].[ManagerID]
INNER JOIN [Person].[Contact] c
ON e.[ContactID] = c.[ContactID]
)
-- Join back to Employee to return the manager name
SELECT [EMP_cte].[RecursionLevel] , [EMP_cte].[EmployeeID], [EMP_cte].[FirstName], [EMP_cte].[LastName],
[EMP_cte].[ManagerID], c.[FirstName] AS 'ManagerFirstName', c.[LastName] AS 'ManagerLastName' -- Outer select from the CTE
FROM [EMP_cte]
INNER JOIN [HumanResources].[Employee ] e
ON [EMP_cte].[ManagerID] = e.[EmployeeID]
INNER JOIN [Person].[Contact] c
ON e.[ContactID] = c.[ContactID]
ORDER BY [RecursionLevel], [ManagerID], [EmployeeID]
OPTION (MAXRECURSION 25)
END;
CREATE PROCEDURE [dbo].[uspGetEmployeeManag
@EmployeeID [int]
AS
BEGIN
SET NOCOUNT ON;
-- Use recursive query to list out all Employees required for a particular Manager
WITH [EMP_cte]([EmployeeID], [ManagerID], [FirstName], [LastName], [Title], [RecursionLevel]) -- CTE name and columns
AS (
SELECT e.[EmployeeID], e.[ManagerID], c.[FirstName], c.[LastName], e.[Title], 0 -- Get the initial Employee
FROM [HumanResources].[Employee
INNER JOIN [Person].[Contact] c
ON e.[ContactID] = c.[ContactID]
WHERE e.[EmployeeID] = @EmployeeID
UNION ALL
SELECT e.[EmployeeID], e.[ManagerID], c.[FirstName], c.[LastName], e.[Title], [RecursionLevel] + 1 -- Join recursive member to anchor
FROM [HumanResources].[Employee
INNER JOIN [EMP_cte]
ON e.[EmployeeID] = [EMP_cte].[ManagerID]
INNER JOIN [Person].[Contact] c
ON e.[ContactID] = c.[ContactID]
)
-- Join back to Employee to return the manager name
SELECT [EMP_cte].[RecursionLevel]
[EMP_cte].[ManagerID], c.[FirstName] AS 'ManagerFirstName', c.[LastName] AS 'ManagerLastName' -- Outer select from the CTE
FROM [EMP_cte]
INNER JOIN [HumanResources].[Employee
ON [EMP_cte].[ManagerID] = e.[EmployeeID]
INNER JOIN [Person].[Contact] c
ON e.[ContactID] = c.[ContactID]
ORDER BY [RecursionLevel], [ManagerID], [EmployeeID]
OPTION (MAXRECURSION 25)
END;
Hi,
that's very simple: This procedure uses recursion to find the manager and the complete tree above up to the highest level. Simply leave out the recursion and you get the direct manager only.
If you also delete the WHERE statement in the anchor element you get all employees with their direct manager (the procedure doesn't use the organizationNode to find that out):
Cheers,
Christian
that's very simple: This procedure uses recursion to find the manager and the complete tree above up to the highest level. Simply leave out the recursion and you get the direct manager only.
If you also delete the WHERE statement in the anchor element you get all employees with their direct manager (the procedure doesn't use the organizationNode to find that out):
CREATE PROCEDURE [dbo].[uspGetEmployeeManagers]
AS
BEGIN
SET NOCOUNT ON;
-- Use recursive query to list out all Employees required for a particular Manager
WITH [EMP_cte]([EmployeeID], [ManagerID], [FirstName], [LastName], [Title]) -- CTE name and columns
AS (
SELECT e.[EmployeeID], e.[ManagerID], c.[FirstName], c.[LastName], e.[Title] -- Get the initial Employee
FROM [HumanResources].[Employee] e
INNER JOIN [Person].[Contact] c
ON e.[ContactID] = c.[ContactID]
)
-- Join back to Employee to return the manager name
SELECT [EMP_cte].[EmployeeID], [EMP_cte].[FirstName], [EMP_cte].[LastName],
[EMP_cte].[ManagerID], c.[FirstName] AS 'ManagerFirstName', c.[LastName] AS 'ManagerLastName' -- Outer select from the CTE
FROM [EMP_cte]
INNER JOIN [HumanResources].[Employee] e
ON [EMP_cte].[ManagerID] = e.[EmployeeID]
INNER JOIN [Person].[Contact] c
ON e.[ContactID] = c.[ContactID]
ORDER BY [ManagerID], [EmployeeID]
END;
Cheers,
Christian
ASKER
This is the correct procedure with OrganizationNode
CREATE PROCEDURE [dbo].[uspGetEmployeeManag ers]
BEGIN
SET NOCOUNT ON;
-- Use recursive query to list out all Employees required for a particular Manager
WITH [EMP_cte]([BusinessEntityI D], [OrganizationNode], [FirstName], [LastName], [JobTitle], [RecursionLevel]) -- CTE name and columns
AS (
SELECT e.[BusinessEntityID], e.[OrganizationNode], p.[FirstName], p.[LastName], e.[JobTitle], 0 -- Get the initial Employee
FROM [HumanResources].[Employee ] e
INNER JOIN [Person].[Person] as p
ON p.[BusinessEntityID] = e.[BusinessEntityID]
WHERE e.[BusinessEntityID] = @BusinessEntityID
UNION ALL
SELECT e.[BusinessEntityID], e.[OrganizationNode], p.[FirstName], p.[LastName], e.[JobTitle], [RecursionLevel] + 1 -- Join recursive member to anchor
FROM [HumanResources].[Employee ] e
INNER JOIN [EMP_cte]
ON e.[OrganizationNode] = [EMP_cte].[OrganizationNod e].GetAnce stor(1)
INNER JOIN [Person].[Person] p
ON p.[BusinessEntityID] = e.[BusinessEntityID]
)
-- Join back to Employee to return the manager name
SELECT [EMP_cte].[RecursionLevel] , [EMP_cte].[BusinessEntityI D], [EMP_cte].[FirstName], [EMP_cte].[LastName],
[EMP_cte].[OrganizationNod e].ToStrin g() AS [OrganizationNode], p.[FirstName] AS 'ManagerFirstName', p.[LastName] AS 'ManagerLastName' -- Outer select from the CTE
FROM [EMP_cte]
INNER JOIN [HumanResources].[Employee ] e
ON [EMP_cte].[OrganizationNod e].GetAnce stor(1) = e.[OrganizationNode]
INNER JOIN [Person].[Person] p
ON p.[BusinessEntityID] = e.[BusinessEntityID]
ORDER BY [RecursionLevel], [EMP_cte].[OrganizationNod e].ToStrin g()
OPTION (MAXRECURSION 25)
END;
CREATE PROCEDURE [dbo].[uspGetEmployeeManag
BEGIN
SET NOCOUNT ON;
-- Use recursive query to list out all Employees required for a particular Manager
WITH [EMP_cte]([BusinessEntityI
AS (
SELECT e.[BusinessEntityID], e.[OrganizationNode], p.[FirstName], p.[LastName], e.[JobTitle], 0 -- Get the initial Employee
FROM [HumanResources].[Employee
INNER JOIN [Person].[Person] as p
ON p.[BusinessEntityID] = e.[BusinessEntityID]
WHERE e.[BusinessEntityID] = @BusinessEntityID
UNION ALL
SELECT e.[BusinessEntityID], e.[OrganizationNode], p.[FirstName], p.[LastName], e.[JobTitle], [RecursionLevel] + 1 -- Join recursive member to anchor
FROM [HumanResources].[Employee
INNER JOIN [EMP_cte]
ON e.[OrganizationNode] = [EMP_cte].[OrganizationNod
INNER JOIN [Person].[Person] p
ON p.[BusinessEntityID] = e.[BusinessEntityID]
)
-- Join back to Employee to return the manager name
SELECT [EMP_cte].[RecursionLevel]
[EMP_cte].[OrganizationNod
FROM [EMP_cte]
INNER JOIN [HumanResources].[Employee
ON [EMP_cte].[OrganizationNod
INNER JOIN [Person].[Person] p
ON p.[BusinessEntityID] = e.[BusinessEntityID]
ORDER BY [RecursionLevel], [EMP_cte].[OrganizationNod
OPTION (MAXRECURSION 25)
END;
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
by adding WHERE RecursionLevel = 1 gave me the result I was waiting for.
Thank you for your feedback
Thank you for your feedback
you cannot expect thatyou understand that just by looking into the data. The hierarchy ID is a new "datatype" since SQL Server 2008 and it is a sort of materialized path (you'll find a lot about that using that in a search machine).
Here are two samples of sites which explains this ID in deep, especially the article(s) of Itzik Ben-Gan are most valueable:
http://msdn.microsoft.com/en-us/library/bb677173%28v=sql.110%29.aspx
http://sqlmag.com/t-sql/hierarchyid
You will need to read that to understand the theory behind that kind of datatype.
Cheers,
Christian
BTW: That has nothing to do with Access...