Last active
November 5, 2019 17:39
-
-
Save kevinwucodes/d7d0efb74935ac48e24b8ebe208927ae to your computer and use it in GitHub Desktop.
sql - recursive employee hierarchy pinpointing a direct manager (with hierarchical order)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--taken directly from https://blogs.msdn.microsoft.com/simonince/2007/10/17/hierarchies-with-common-table-expressions/ | |
--order logic taken from https://stackoverflow.com/questions/32858774/how-to-order-rows-by-hierarchy | |
/* | |
Org chart | |
---------- | |
matt (1) | |
kirk (2) | |
chris (3) | |
tom (4) | |
manny (5) | |
tim (6) | |
student1 (7) | |
student2 (8) | |
kush (9) | |
student3 (10) | |
student4 (11) | |
*/ | |
;with emps as ( | |
select * | |
from ( | |
values | |
(1, 'matt', null) --top of the organization, no manager | |
,(2, 'kirk', 1) | |
,(3, 'chris', 2) | |
,(4, 'tom', 2) | |
,(5, 'manny', 1) | |
,(6, 'tim', 5) | |
,(7, 'student1', 6) | |
,(8, 'student2', 6) | |
,(9, 'kush', 5) | |
,(10, 'student3', 9) | |
,(11, 'student4', 9) | |
) s (id, name, managerId) | |
) | |
,org as ( | |
select level = 1 | |
,emps.id | |
,emps.name | |
,emps.managerId | |
,root = emps.id | |
--we begin the sort order when the lowest number, because this is the "top" of the organization | |
,sortOrder = cast(1 as real) | |
from emps | |
where 1=1 | |
--we dont really need filters here, because we assign a root Id for every person in the employees table, then recursively work our way down. | |
--notice that we do not alter the root Id in the second select because we dont want to modify it | |
--and managerId is null | |
--and id = 5 | |
union all | |
select level + 1 | |
,emps.id | |
,emps.name | |
,emps.managerId | |
,root | |
--we take the top sort order and calculate their subpositions | |
,sortOrder = org.sortOrder + (CAST(ROW_NUMBER() OVER(ORDER BY emps.name) AS REAL) / POWER(10, org.level)) | |
from emps | |
inner join org on org.id = emps.managerId | |
) | |
select | |
top 100 | |
* | |
from org | |
where root = 1 --put the manager ID here and get all the direct and indirect reports for this manager Id | |
order by sortOrder | |
/* | |
level id name managerId root sortOrder | |
----------- ----------- -------- ----------- ----------- ------------- | |
1 1 matt NULL 1 1 | |
2 2 kirk 1 1 1.1 | |
3 3 chris 2 1 1.11 | |
3 4 tom 2 1 1.12 | |
2 5 manny 1 1 1.2 | |
3 9 kush 5 1 1.21 | |
4 10 student3 9 1 1.211 | |
4 11 student4 9 1 1.212 | |
3 6 tim 5 1 1.22 | |
4 7 student1 6 1 1.221 | |
4 8 student2 6 1 1.222 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment