具有两个表的SQL递归CTE

时间:2018-08-29 20:58:29

标签: sql sqlite recursion common-table-expression

尝试绕过递归CTE,但遇到了一些麻烦。我有两张桌子,一张给员工,一张给部门。我正在尝试编写一个递归CTE,该CTE从锚定部门开始并遍历所有子部门,将一组具有外键的员工返回到锚定部门或任何子部门。

这是employee表的简化版本

employeeID     name               departmentID
1              Brad Fisher        1
2              Alex McCabe        2
3              Amy Calvin         2
4              Daniel Struthers   4

和部门表。 parentID只是引用同一表中的其他部门。

departmentID    name                      parentID
1               Company Operations        0
2               Guest Services            1
3               Staff Services            1
4               IT Support                3

以下是我汇总的CTE。只要部门层次结构的每个级别中至少有一名雇员,它将从顶部开始返回所有雇员的完整列表。但是问题是,如果层次结构中有一个部门没有雇员,那么它将破坏递归。

WITH EmployeeDepartmentHierarchy(employeeID, name, departmentID)
AS (
   SELECT e.employeeID,
          e.name,
          e.departmentID
   FROM Departments AS d
   INNER JOIN Employees AS e ON d.departmentID = e.departmentID
   WHERE d.name = "Company Operations"
   UNION ALL
   SELECT e.employeeID,
          e.name,
          d.deparmentID
   FROM Departments AS d
   INNER JOIN EmployeeDepartmentHierarchy AS edh ON edh.departmentID = d.parentID
   LEFT JOIN Employees AS e ON d.departmentID = e.departmentID
   )
   SELECT * FROM EmployeeDepartmentHierarchy

我正在尝试对其进行修复,以使其在整个部门层次结构中消失,并且仅在找不到子部门时才终止,而不是在到达没有员工的部门时终止。

1 个答案:

答案 0 :(得分:1)

正如wildplasser所言,将没有员工的部门纳入CTE,然后将其留在外部查询中。

WITH dh
     (departmentid)
AS
(
SELECT d.departmentid
       FROM departments d
       WHERE d.name = 'Company Operations'
UNION ALL
SELECT d.departmentid
       FROM departments d
            INNER JOIN dh
                       ON dh.departmentid = d.parentid
)
SELECT e.employeeid,
       e.name,
       dh.departmentid
       FROM dh
            LEFT JOIN employees e
                      ON e.departmentid = dh.departmentid;

db<>fiddle