sql - 如何从自引用表中确定每个人的结构

标签 sql hierarchy self-join pervasive-sql

我有以下表格:

Employees
-------------
ClockNo     int
CostCentre  varchar
Department  int


Departments
-------------
DepartmentCode  int
CostCentreCode  varchar
Parent          int

部门可以有其他部门作为父部门,这意味着存在无限的层次结构。所有部门都属于一个成本中心,因此总是有一个 CostCentreCode .如 parent = 0这是一个顶级部门

员工必须拥有 CostCentre值但可能有 Department 0 表示他们不在一个部门

我想尝试和生成的是一个查询,最多可以提供四个层次结构。像这样:
EmployeesLevels
-----------------
ClockNo
CostCentre
DeptLevel1
DeptLevel2
DeptLevel3
DeptLevel4

我已经设法得到一些东西来显示自己的部门结构,但我无法弄清楚如何在不创建重复员工行的情况下将其链接到员工:
SELECT d1.Description AS lev1, d2.Description as lev2, d3.Description as lev3, d4.Description as lev4
FROM departments AS d1
LEFT JOIN departments AS d2 ON d2.parent = d1.departmentcode
LEFT JOIN departments AS d3 ON d3.parent = d2.departmentcode
LEFT JOIN departments AS d4 ON d4.parent = d3.departmentcode
WHERE d1.parent=0;

SQL 创建结构和一些示例数据:
CREATE TABLE Employees(
ClockNo integer NOT NULL PRIMARY KEY,
CostCentre varchar(20) NOT NULL,
Department integer NOT NULL);

CREATE TABLE Departments(
DepartmentCode integer NOT NULL PRIMARY KEY,
CostCentreCode varchar(20) NOT NULL,
Parent integer NOT NULL
);

CREATE INDEX idx0 ON Employees (ClockNo);
CREATE INDEX idx1 ON Employees (CostCentre, ClockNo);
CREATE INDEX idx2 ON Employees (CostCentre);

CREATE INDEX idx0 ON Departments (DepartmentCode);
CREATE INDEX idx1 ON Departments (CostCentreCode, DepartmentCode);

INSERT INTO Employees VALUES (1, 'AAA', 0);
INSERT INTO Employees VALUES (2, 'AAA', 3);
INSERT INTO Employees VALUES (3, 'BBB', 0);
INSERT INTO Employees VALUES (4, 'BBB', 4);
INSERT INTO Employees VALUES (5, 'CCC', 0); 
INSERT INTO Employees VALUES (6, 'AAA', 1);
INSERT INTO Employees VALUES (7, 'AAA', 5);
INSERT INTO Employees VALUES (8, 'AAA', 15);

INSERT INTO Departments VALUES (1, 'AAA', 0);
INSERT INTO Departments VALUES (2, 'AAA', 1);
INSERT INTO Departments VALUES (3, 'AAA', 1);
INSERT INTO Departments VALUES (4, 'BBB', 0);
INSERT INTO Departments VALUES (5, 'AAA', 3);
INSERT INTO Departments VALUES (12, 'AAA', 5);
INSERT INTO Departments VALUES (15, 'AAA', 12);

这给出了以下结构(方括号中的员工时钟编号):
Root
  |
  |---AAA                   [1]
  |    \---1                [6]
  |       |---2     
  |       \---3             [2]
  |          \---5          [7]
  |             \---12
  |                \---15   [8]
  |
  |---BBB                   [3]
  |    \---4                [4]
  |
  \---CCC                   [5]

查询应返回以下内容:
ClockNo CostCentre Level1 Level2 Level3 Level4
1       AAA        
2       AAA        1      3
3       BBB
4       BBB        4
5       CCC
6       AAA        1
7       AAA        1      3       5
8       AAA        1      3       5      12  *
*在员工 8 的情况下,他们处于级别 5。理想情况下,我想显示所有级别到 4 级,但我很高兴在这种情况下只显示 CostCentre

最佳答案

当我们加入表时,当我们找到属于上一级员工的适当部门时,我们应该停止进一步遍历路径。

当 Employee.Department=0 时,我们也有异常(exception)情况。在这种情况下我们不应该加入任何部门,因为在这种情况下部门是根。

我们只需要选择包含其中一个级别的员工部门的那些记录。
如果员工的部门级别大于 4,我们应该扩展所有 4 个级别的部门并按原样显示它们(即使无法达到所需的部门级别并且没有在扩展的部门中找到它)。

select e.ClockNo, 
       e.CostCentre, 
       d1.DepartmentCode as Level1, 
       d2.DepartmentCode as Level2, 
       d3.DepartmentCode as Level3, 
       d4.DepartmentCode as Level4
from Employees e
left join Departments d1 
          on e.CostCentre=d1.CostCentreCode 
          and d1.Parent=0 
          and ((d1.DepartmentCode = 0 and e.Department = 0) or e.Department <> 0)
left join Departments d2 
          on d2.parent=d1.DepartmentCode 
          and (d1.DepartMentCode != e.Department and e.Department<>0)
left join Departments d3 
          on d3.parent=d2.DepartmentCode 
          and (d2.DepartMentCode != e.Department and e.Department<>0)
left join Departments d4 
          on d4.parent=d3.DepartmentCode 
          and (d3.DepartMentCode != e.Department and e.Department<>0)
where e.Department=d1.DepartmentCode 
      or e.Department=d2.DepartmentCode 
      or e.Department=d3.DepartmentCode 
      or e.Department=d4.DepartmentCode 
      or e.Department=0
      or (
        (d1.DepartmentCode is not null) and
        (d2.DepartmentCode is not null) and
        (d3.DepartmentCode is not null) and
        (d4.DepartmentCode is not null)
      )
order by e.ClockNo;

关于sql - 如何从自引用表中确定每个人的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36647523/

相关文章:

线性层次结构的 C++ 可变参数模板参数

c# - 从结构化数据构建 JSON 层次结构

sql - 如何使用自连接更快地进行查询?

mysql - 简单的MySQL自连接查询,想要获取每个重复条目的ID列

mysql - 如何使用Group By和self-join返回min, max, open, close daily price result set?

java - HQL JAVA - 如何使用多个列表创建组合条件

sql - SQL 'not in' 比 SQL 'expensive' 多 'in' 吗?

MySQL 脚本触发错误 #1241

sql - 缺少数据的窗口函数

xml - 在 xml 层次结构中向上移动分隔符元素