Reputation: 13
IF (Object_ID('Employee1') is Not Null)
Drop Table Employee1
Create Table Employee1(
EID int primary key,
Name varchar(50),
MID int references Employee1(EID)
)
Insert into Employee1 values
(1,'Peter',2),
(2,'Nancy',3),
(3,'Bob',null),
(4,'Philip',5),
(5,'Jason',3),
(6,'Gilbert',5)
Get me EID, Name of all employees who are manager of managers
Below is the query I wrote for that question
select distinct
e1.eid,
e1.name,
e1.mid
from employee1 e1
inner join employee1 e2 on e1.eid = e2.mid
inner join employee1 e3 on e3.mid = e2.eid
But I couldn't find how this query is working. It's giving me the correct answer but, how I don't know.
Can anyone explain how this query is executing step by step. Thanks in advance.
Upvotes: 1
Views: 138
Reputation: 35323
My initial thought was this was going up the chain; it looks like it's going down the chain after closer review. So each manager must have at least 2 levels of subordinates before that manager could be returned. If they do not have at least two levels; the manager would not be returned.
So the query joins to employee1 table 2 times each time on MID assuming MID is managerID. As each join is an INNER Join only managers who have employees and employees who have employees will be returned. This means only managers who have at least 2 levels of employees below them will be returned; and of those only distinct employees will be returned.
Break it down:
The 1st join will return all managers and their employees . The 2nd join will return all managers and their employees
So the results will be a distinct list of all managers from the main employee table but only if they have employees, and their employees has a employee due to the nature of inner join only returning records if they exist in the associated table.
There are other ways to do this as well using recursive CTE's instead of having to use a separate join for each level you want to track; thus negating the need to add joins for each level required.
With CTE AS (
SELECT eid EID , name NAME , mid MID, 1 as Depth
FROM EMPLOYEE1
WHERE MID is not null
UNION ALL
--This union all is part of the recursion magic
SELECT E1.eid,e1.name,e1.mid, Depth+1
FROM Employee1 E1
--This is where it gets really weird. We're doing a join to the CTE itself from within the CTE... That's recursion.
INNER JOIN CTE E2
on E2.MID=E1.EID
)
SELECT Distinct * FROM CTE
WHERE DEPTH = 3
;
Resulting in:
+----+-----+------+------+-------+
| | EID | NAME | MID | Depth |
+----+-----+------+------+-------+
| 1 | 3 | Bob | NULL | 3 |
+----+-----+------+------+-------+
Upvotes: 1