Mat*_*lko 7 sql hierarchy self-join pervasive-sql
我有以下表格:
Employees
-------------
ClockNo int
CostCentre varchar
Department int
Run Code Online (Sandbox Code Playgroud)
和
Departments
-------------
DepartmentCode int
CostCentreCode varchar
Parent int
Run Code Online (Sandbox Code Playgroud)
部门可以将其他部门作为父母,这意味着存在无限的等级.所有部门都属于成本中心,因此总是有一个CostCentreCode
.如果parent = 0
是顶级部门
员工必须具有CostCentre
价值,但可能具有Department
0,这意味着他们不在某个部门
我想要尝试生成的是一个查询,它将提供最多四层次的层次结构.像这样:
EmployeesLevels
-----------------
ClockNo
CostCentre
DeptLevel1
DeptLevel2
DeptLevel3
DeptLevel4
Run Code Online (Sandbox Code Playgroud)
我已经设法得到一些东西来显示它自己的部门结构,但我无法弄清楚如何在不创建重复的员工行的情况下将其链接到员工:
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;
Run Code Online (Sandbox Code Playgroud)
SQL要创建Structure和一些示例数据:
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);
Run Code Online (Sandbox Code Playgroud)
这给出了以下结构(员工时钟数字在方括号中):
Root
|
|---AAA [1]
| \---1 [6]
| |---2
| \---3 [2]
| \---5 [7]
| \---12
| \---15 [8]
|
|---BBB [3]
| \---4 [4]
|
\---CCC [5]
Run Code Online (Sandbox Code Playgroud)
该查询应返回以下内容:
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 *
Run Code Online (Sandbox Code Playgroud)
*
在员工8的情况下,他们在5级.理想情况下,我希望将所有级别显示为level4,但我很高兴在这种情况下显示CostCentre
SunnyMagadan 的询问很好。但是,根据部门中的员工数量,您可能希望尝试以下方法,这使数据库优化器有机会为一个部门仅遍历一次部门层次结构,而不是为部门中的每个员工重复一次。
SELECT e.ClockNo, e.CostCentre, Level1, Level2, Level3, Level4
FROM Employees e
LEFT JOIN
(SELECT
d1.departmentcode
, d1.CostCentreCode
, coalesce (d4.departmentcode, d3.departmentcode
, d2.departmentcode, d1.departmentcode) AS Level1
, case when d4.departmentcode is not null then d3.departmentcode
when d3.departmentcode is not null then d2.departmentcode
when d2.departmentcode is not null then d1.departmentcode end as Level2
, case when d4.departmentcode is not null then d2.departmentcode
when d3.departmentcode is not null then d1.departmentcode end as Level3
, case when d4.departmentcode is not null then d1.departmentcode end as Level4
FROM departments AS d1
LEFT JOIN departments AS d2 ON d1.parent = d2.departmentcode
LEFT JOIN departments AS d3 ON d2.parent = d3.departmentcode
LEFT JOIN departments AS d4 ON d3.parent = d4.departmentcode) d
ON d.DepartmentCode = e.Department AND d.CostCentreCode = e.CostCentre
;
Run Code Online (Sandbox Code Playgroud)
编辑关于 5 级以上部门。
任何固定步骤查询都无法获取它们的前 4 个级别。因此,更改上面的查询只是为了以某种方式标记它们,例如 -1。
, case when d4.Parent > 0 then NULL else
coalesce (d4.departmentcode, d3.departmentcode
, d2.departmentcode, d1.departmentcode) end AS Level1
Run Code Online (Sandbox Code Playgroud)
等等。