sql - 递归 CTE 通过经理获取员工

标签 sql sql-server database recursion common-table-expression

编写一个递归 CTE,通过经理获取员工。包括以下列:

  • 员工姓氏
  • 员工名字
  • 部门 ID
  • 文件文件夹
  • 经理姓氏
  • 经理名字

名为FileFolder的列用于存储每个员工的绩效评估。请注意,由于经理还可以访问直接或间接向他们报告的所有人员,因此每个经理的文件夹最终将设置为不仅包含他们自己的绩效审核文件,还包含直接报告的每个员工的所有子文件夹给他们。为了帮助实现这一点,还包括一个名为“文件路径”的列,该列将确定并显示每个员工的文件路径名,在子文件夹之间使用 Windows 样式的\,即。格式为 ManagerFileFolder\EmployeeFileFolder\

为了说明这是如何工作的,例如,如果我直接向 Dev Sainani 报告,而 Dev 向 Peter Devlin 报告,那么我的文件路径将是 PeterDevlin\DevSainani\OsamAl

我不确定如何在不更改表的情况下包含不在我提供的数据库表中的列,以及如何合并上面提到的“文件路径”要求。

这是 Employees 表(我提供的唯一表)的脚本:

CREATE TABLE dbo.Employees 
(
    EmployeeID        INT IDENTITY PRIMARY KEY,
    DepartmentID      INT 
        CONSTRAINT FK_Employee_Department 
            FOREIGN KEY REFERENCES dbo.Departments (DepartmentID),
    ManagerEmployeeID INT 
        CONSTRAINT FK_Employee_Manager 
            FOREIGN KEY REFERENCES dbo.Employees (EmployeeID),
    FirstName         NVARCHAR(60),
    LastName          NVARCHAR(60),
    Salary            MONEY 
        CONSTRAINT CK_EmployeeSalary CHECK (Salary >= 0),
    CommissionBonus   MONEY 
        CONSTRAINT CK_EmployeeCommission CHECK (CommissionBonus >= 0),
    FileFolder        NVARCHAR(256) 
        CONSTRAINT DF_FileFolder DEFAULT 'ToBeCreated'
);

这就是我所做的,我知道它不正确,因为当我为此 CTE 编写 SELECT 语句时,我没有得到表中显示的任何数据:

WITH GetEmployeeByManager AS 
(
    SELECT 
        FirstName, LastName, DepartmentID, FileFolder
    FROM 
        dbo.Employees
    WHERE 
        ManagerEmployeeID IS NULL

    UNION ALL

    SELECT 
        e.LastName, e.FirstName, e.DepartmentID, e.FileFolder
    FROM 
        Employees e
    JOIN 
        GetEmployeeByManager ge ON e.ManagerEmployeeID = ge.ManagerEmployeeID
)
SELECT *
FROM GetEmployeeByManager ge
JOIN dbo.Employees e ON ge.ManagerEmployeeID = e.ManagerEmployeeID;

最佳答案

此脚本将为您提供您所描述的所需输出。在 CREATE 表语句中,为了简单起见,我删除了外键约束,因为我使用 SQL Fiddle 构建此查询。

SQL Fiddle

MS SQL Server 2017 架构设置:

CREATE TABLE Employees 
(
    EmployeeID        INT not null PRIMARY KEY,
    DepartmentID      INT not null,
    ManagerEmployeeID INT null,
    FirstName         NVARCHAR(60),
    LastName          NVARCHAR(60),
    Salary            MONEY 
        CONSTRAINT CK_EmployeeSalary CHECK (Salary >= 0),
    CommissionBonus   MONEY 
        CONSTRAINT CK_EmployeeCommission CHECK (CommissionBonus >= 0),
    FileFolder        NVARCHAR(256) 
        CONSTRAINT DF_FileFolder DEFAULT 'ToBeCreated'
);

INSERT INTO Employees (EmployeeID, DepartmentID, ManagerEmployeeID, FirstName, LastName, Salary, CommissionBonus, FileFolder)
VALUES (1, 101, null, 'Ted', 'Smith', 12000.00, 120.00, 'TedSmith')
  , (2, 101, 1, 'John','Doe', 10000.00, 100.00, 'JohnDoe')
  , (3, 101, 2, 'Dev', 'Patel', 8000.00, 80.00, 'DevPatel')
;

查询 1:

WITH GetEmployeeByManager AS 
(
    SELECT 
        e.EmployeeID
        , e.FirstName
        , e.LastName
        , e.DepartmentID
        , e.ManagerEmployeeID
        , em.FirstName as ManagerFirstName
        , em.LastName as ManagerLastName
        , e.FileFolder
        , e.FileFolder as FilePath
        , 0 as hierarchy_level
    FROM Employees as e
        LEFT OUTER JOIN Employees as em
            ON em.EmployeeID = e.ManagerEmployeeID
    WHERE e.ManagerEmployeeID is null --First query gets only managers

    UNION ALL

    SELECT 
        e.EmployeeID
        , e.FirstName
        , e.LastName
        , e.DepartmentID
        , e.ManagerEmployeeID
        , em.FirstName as ManagerFirstName
        , em.LastName as ManagerLastName
        , e.FileFolder
        , CAST(em.FilePath + '/' + e.FileFolder as nvarchar(256)) as FileFolder
        , em.hierarchy_level + 1 as hierarchy_level
    FROM Employees e
        INNER JOIN GetEmployeeByManager as em
            ON em.EmployeeID = e.ManagerEmployeeID
    WHERE em.hierarchy_level < 50
)
SELECT *
FROM GetEmployeeByManager ge

<强> Results :

| EmployeeID | FirstName | LastName | DepartmentID | ManagerEmployeeID | ManagerFirstName | ManagerLastName | FileFolder |                  FilePath | hierarchy_level |
|------------|-----------|----------|--------------|-------------------|------------------|-----------------|------------|---------------------------|-----------------|
|          1 |       Ted |    Smith |          101 |            (null) |           (null) |          (null) |   TedSmith |                  TedSmith |               0 |
|          2 |      John |      Doe |          101 |                 1 |              Ted |           Smith |    JohnDoe |          TedSmith/JohnDoe |               1 |
|          3 |       Dev |    Patel |          101 |                 2 |             John |             Doe |   DevPatel | TedSmith/JohnDoe/DevPatel |               2 |

关于sql - 递归 CTE 通过经理获取员工,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74426304/

相关文章:

c# - System.Data.dll ("Incorrect syntax near ' )'."中的“System.Data.SqlClient.SqlException”)?

sql-server - 会计和数据库设计,存储借贷金额

sql - AWS RDS : specifying lc_collate and lc_ctype for PostgreSQL

mysql - 如何根据关联表中的值更新多个列?

sql-server - 在 sql server 中将列值设置为 not null 时,我是否必须为该列设置一个默认值,或者它应该仍然有效吗?

sql-server - 在 SQL Server 中对大量数据执行操作的最佳方法是什么?

database - 我应该将计算值与变量一起存储在我的数据库中吗?

sql - 减少 DB2 列长度的方法

用于搜索房间可用性的 SQL 查询

c# - 在 UWP 中连接到数据库时无法加载文件或程序集