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

前端之家收集整理的这篇文章主要介绍了sql – 如何从自引用表中确定每个人的结构前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有以下表格:
Employees
-------------
ClockNo     int
CostCentre  varchar
Department  int

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

部门可以将其他部门作为父母,这意味着存在无限的等级.所有部门都属于成本中心,因此始终具有CostCentreCode.如果parent = 0,则它是顶级部门

员工必须具有CostCentre值,但可能具有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要创建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,3);
INSERT INTO Employees VALUES (3,'BBB',0);
INSERT INTO Employees VALUES (4,4);
INSERT INTO Employees VALUES (5,'CCC',0); 
INSERT INTO Employees VALUES (6,1);
INSERT INTO Employees VALUES (7,5);
INSERT INTO Employees VALUES (8,15);

INSERT INTO Departments VALUES (1,0);
INSERT INTO Departments VALUES (2,1);
INSERT INTO Departments VALUES (3,1);
INSERT INTO Departments VALUES (4,0);
INSERT INTO Departments VALUES (5,3);
INSERT INTO Departments VALUES (12,5);
INSERT INTO Departments VALUES (15,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级.理想情况下,我希望将所有级别显示为level4,但我很高兴在这种情况下显示CostCentre

解决方法

SunnyMagadan的查询很好.但是,根据部门中的员工数量,您可能希望尝试以下方法,使DB优化器有机会仅为部门遍历部门层次结构而不是为部门中的每个员工重复一次.
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
;

编辑关于5级部门.

任何固定步骤查询都无法获得前4个级别.因此,更改上面的查询只是为了标记它们,例如-1.

,case when d4.Parent > 0 then NULL else 
    coalesce (d4.departmentcode,d1.departmentcode) end AS Level1

等等.

猜你在找的MsSQL相关文章