如何获得在主管下工作的各级员工名单?
How to get list of all levels of employees working under supervisor?
我需要将员工列表缩小到在特定主管或主管或经理手下工作的最低级别。
下面是员工的等级制度,每个员工都有一个主管,主管向主管报告,主管向经理报告如下:
table中的数据只有如下2个字段:
我的 SQL 查询是 SELECT Employee_ID FROM DATABASE_TABLE WHERE Supervisor_ID='Joe'
。结果是我得到了向 Joe
报告的所有员工的最低级别列表。同样,如果我查询 Supervisor_ID='David'
,我应该让所有向 David
报告的员工的最低级别。
我在 Oracle 中有使用 CONNECT_BY_PATH
进行此类查询的经验,但我不知道如何在 MS SQL 中实现这一点。一个例子将是非常可观的。谢谢。
Create Table and Insert Statements:
CREATE TABLE DATABASE_TABLE(Employee_ID varchar(255),Supervisor_ID varchar(255));
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Alice','Dave');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Olive','Dave');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Barton','Dave');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Almira','Jacob');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Charles','Jacob');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Davis','Jacob');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Robert','Risha');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Peter','Risha');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Ethel','Risha');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Isaac','Jospeh');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Sophia','Jospeh');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Rosa','Jospeh');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Joshua','Dandy');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Silas','Dandy');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Fred','Dandy');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Frank','Andrew');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Howard','Andrew');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Ralph','Andrew');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Dennis','Henry');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Alex','Henry');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Floyd','Henry');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Carlos','Nelson');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Homer','Nelson');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Harold','Nelson');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Leo','Simon');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Warren','Simon');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Clifford','Simon');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Martha','Casper');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Hazel','Casper');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Irene','Casper');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Dave','Betsy');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Jacob','Betsy');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Risha','David');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Jospeh','David');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Dandy','Phillip');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Andrew','Phillip');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Henry','Harvey');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Nelson','Harvey');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Simon','Paul');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Casper','Paul');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Betsy','Joe');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('David','Joe');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Phillip','Joe');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Harvey','Joe');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Paul','Joe');
这里有一个示例,可以让您了解递归 CTE 的用途。
示例数据:
CREATE TABLE DATABASE_TABLE
(
Employee_Name nvarchar(255) PRIMARY KEY,
Supervisor_Name nvarchar(255) NOT NULL
);
CREATE INDEX [ix_database_table_supervisor]
ON DATABASE_TABLE (Supervisor_Name);
GO
INSERT INTO DATABASE_TABLE
(Employee_Name, Supervisor_Name) VALUES
('Alice','Dave')
, ('Olive','Dave')
, ('Barton','Dave')
, ('Almira','Jacob')
, ('Charles','Jacob')
, ('Davis','Jacob')
, ('Robert','Risha')
, ('Peter','Risha')
, ('Ethel','Risha')
, ('Isaac','Jospeh')
, ('Sophia','Jospeh')
, ('Rosa','Jospeh')
, ('Joshua','Dandy')
, ('Silas','Dandy')
, ('Fred','Dandy')
, ('Frank','Andrew')
, ('Howard','Andrew')
, ('Ralph','Andrew')
, ('Dennis','Henry')
, ('Alex','Henry')
, ('Floyd','Henry')
, ('Carlos','Nelson')
, ('Homer','Nelson')
, ('Harold','Nelson')
, ('Leo','Simon')
, ('Warren','Simon')
, ('Clifford','Simon')
, ('Martha','Casper')
, ('Hazel','Casper')
, ('Irene','Casper')
, ('Dave','Betsy')
, ('Jacob','Betsy')
, ('Risha','David')
, ('Jospeh','David')
, ('Dandy','Phillip')
, ('Andrew','Phillip')
, ('Henry','Harvey')
, ('Nelson','Harvey')
, ('Simon','Paul')
, ('Casper','Paul')
, ('Betsy','Joe')
, ('David','Joe')
, ('Phillip','Joe')
, ('Harvey','Joe')
, ('Paul','Joe')
查询:
DECLARE @HeadName nvarchar(255);
SET @HeadName = 'David';
DECLARE @MaxLvl INT = 2;
WITH RCTE_DATA AS
(
-- seeding the recursion
SELECT
t.Employee_Name AS Head_Name,
t.Supervisor_Name AS Manager_Name,
0 AS Lvl,
t.Employee_Name,
t.Supervisor_Name
FROM DATABASE_TABLE t
WHERE t.Employee_Name = @HeadName
UNION ALL
-- looping the recursion
SELECT
c.Head_Name,
c.Manager_Name,
c.Lvl + 1,
t.Employee_Name,
t.Supervisor_Name
FROM RCTE_DATA c
JOIN DATABASE_TABLE t
ON t.Supervisor_Name = c.Employee_Name
WHERE c.Lvl < @MaxLvl
)
SELECT
Employee_Name,
Supervisor_Name,
Head_Name,
Manager_Name
FROM RCTE_DATA
WHERE Lvl = @MaxLvl
结果:
Employee_Name | Supervisor_Name | Head_Name | Manager_Name
:------------ | :-------------- | :-------- | :-----------
Ethel | Risha | David | Joe
Peter | Risha | David | Joe
Robert | Risha | David | Joe
Isaac | Jospeh | David | Joe
Rosa | Jospeh | David | Joe
Sophia | Jospeh | David | Joe
db<>fiddle here
select * from (
SELECT a.Employee_Name, a.Supervisor_Name, b.Supervisor_Name as Head_Name, c.Supervisor_Name as Manager_Name
FROM DATABASE_TABLE a
LEFT JOIN DATABASE_TABLE b ON a.Supervisor_Name = b.Employee_Name
LEFT JOIN DATABASE_TABLE c ON b.Supervisor_Name = c.Employee_Name) as t
where t.Head_Name='David'
order by Supervisor_Name ;
我需要将员工列表缩小到在特定主管或主管或经理手下工作的最低级别。
下面是员工的等级制度,每个员工都有一个主管,主管向主管报告,主管向经理报告如下:
table中的数据只有如下2个字段:
我的 SQL 查询是 SELECT Employee_ID FROM DATABASE_TABLE WHERE Supervisor_ID='Joe'
。结果是我得到了向 Joe
报告的所有员工的最低级别列表。同样,如果我查询 Supervisor_ID='David'
,我应该让所有向 David
报告的员工的最低级别。
我在 Oracle 中有使用 CONNECT_BY_PATH
进行此类查询的经验,但我不知道如何在 MS SQL 中实现这一点。一个例子将是非常可观的。谢谢。
Create Table and Insert Statements:
CREATE TABLE DATABASE_TABLE(Employee_ID varchar(255),Supervisor_ID varchar(255));
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Alice','Dave');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Olive','Dave');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Barton','Dave');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Almira','Jacob');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Charles','Jacob');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Davis','Jacob');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Robert','Risha');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Peter','Risha');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Ethel','Risha');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Isaac','Jospeh');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Sophia','Jospeh');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Rosa','Jospeh');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Joshua','Dandy');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Silas','Dandy');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Fred','Dandy');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Frank','Andrew');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Howard','Andrew');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Ralph','Andrew');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Dennis','Henry');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Alex','Henry');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Floyd','Henry');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Carlos','Nelson');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Homer','Nelson');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Harold','Nelson');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Leo','Simon');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Warren','Simon');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Clifford','Simon');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Martha','Casper');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Hazel','Casper');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Irene','Casper');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Dave','Betsy');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Jacob','Betsy');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Risha','David');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Jospeh','David');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Dandy','Phillip');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Andrew','Phillip');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Henry','Harvey');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Nelson','Harvey');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Simon','Paul');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Casper','Paul');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Betsy','Joe');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('David','Joe');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Phillip','Joe');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Harvey','Joe');
INSERT INTO DATABASE_TABLE(Employee_ID, Supervisor_ID) VALUES ('Paul','Joe');
这里有一个示例,可以让您了解递归 CTE 的用途。
示例数据:
CREATE TABLE DATABASE_TABLE ( Employee_Name nvarchar(255) PRIMARY KEY, Supervisor_Name nvarchar(255) NOT NULL ); CREATE INDEX [ix_database_table_supervisor] ON DATABASE_TABLE (Supervisor_Name); GO INSERT INTO DATABASE_TABLE (Employee_Name, Supervisor_Name) VALUES ('Alice','Dave') , ('Olive','Dave') , ('Barton','Dave') , ('Almira','Jacob') , ('Charles','Jacob') , ('Davis','Jacob') , ('Robert','Risha') , ('Peter','Risha') , ('Ethel','Risha') , ('Isaac','Jospeh') , ('Sophia','Jospeh') , ('Rosa','Jospeh') , ('Joshua','Dandy') , ('Silas','Dandy') , ('Fred','Dandy') , ('Frank','Andrew') , ('Howard','Andrew') , ('Ralph','Andrew') , ('Dennis','Henry') , ('Alex','Henry') , ('Floyd','Henry') , ('Carlos','Nelson') , ('Homer','Nelson') , ('Harold','Nelson') , ('Leo','Simon') , ('Warren','Simon') , ('Clifford','Simon') , ('Martha','Casper') , ('Hazel','Casper') , ('Irene','Casper') , ('Dave','Betsy') , ('Jacob','Betsy') , ('Risha','David') , ('Jospeh','David') , ('Dandy','Phillip') , ('Andrew','Phillip') , ('Henry','Harvey') , ('Nelson','Harvey') , ('Simon','Paul') , ('Casper','Paul') , ('Betsy','Joe') , ('David','Joe') , ('Phillip','Joe') , ('Harvey','Joe') , ('Paul','Joe')
查询:
DECLARE @HeadName nvarchar(255); SET @HeadName = 'David'; DECLARE @MaxLvl INT = 2; WITH RCTE_DATA AS ( -- seeding the recursion SELECT t.Employee_Name AS Head_Name, t.Supervisor_Name AS Manager_Name, 0 AS Lvl, t.Employee_Name, t.Supervisor_Name FROM DATABASE_TABLE t WHERE t.Employee_Name = @HeadName UNION ALL -- looping the recursion SELECT c.Head_Name, c.Manager_Name, c.Lvl + 1, t.Employee_Name, t.Supervisor_Name FROM RCTE_DATA c JOIN DATABASE_TABLE t ON t.Supervisor_Name = c.Employee_Name WHERE c.Lvl < @MaxLvl ) SELECT Employee_Name, Supervisor_Name, Head_Name, Manager_Name FROM RCTE_DATA WHERE Lvl = @MaxLvl
结果:
Employee_Name | Supervisor_Name | Head_Name | Manager_Name :------------ | :-------------- | :-------- | :----------- Ethel | Risha | David | Joe Peter | Risha | David | Joe Robert | Risha | David | Joe Isaac | Jospeh | David | Joe Rosa | Jospeh | David | Joe Sophia | Jospeh | David | Joe
db<>fiddle here
select * from (
SELECT a.Employee_Name, a.Supervisor_Name, b.Supervisor_Name as Head_Name, c.Supervisor_Name as Manager_Name
FROM DATABASE_TABLE a
LEFT JOIN DATABASE_TABLE b ON a.Supervisor_Name = b.Employee_Name
LEFT JOIN DATABASE_TABLE c ON b.Supervisor_Name = c.Employee_Name) as t
where t.Head_Name='David'
order by Supervisor_Name ;