使用T-SQL和联接,在表中显示员工的层次结构

时间:2014-01-06 04:32:15

标签: sql sql-server tsql inner-join

我想生成一个这样的表:

+----------------------------------------------------------------+
| Level | PersonName | empid | ManagerID | Code   | ManagerName  |
+----------------------------------------------------------------+
| 1     | BigBoss    | 1     | null      | 00     | null         |
| 2     | Executive1 | 2     | 1         | 0001   | BigBoss      |
| 2     | Executive2 | 3     | 1         | 0002   | BigBoss      |
| 3     | Manager1   | 4     | 2         | 000101 | Executive1   |
| 3     | Manager2   | 5     | 2         | 000102 | Executive1   |
| 3     | Manager3   | 6     | 3         | 000201 | Executive2   |
+----------------------------------------------------------------+

因此,正如您可以看到,与其经理相比,下属的代码中还有2位数,Code确定了层次结构。有时在重组期间,员工的代码不会立即更新,因此编码变得不一致会在表格中产生错误,如下所示:

+----------------------------------------------------------------+
| Level | PersonName | empid | ManagerID | Code   | ManagerName  |
+----------------------------------------------------------------+
| 1     | BigBoss    | 1     | null      | 00     | null         |
| 2     | Executive1 | 2     | 1         | 0001   | BigBoss      |
| 2     | Executive2 | 3     | 1         | 0002   | BigBoss      |
| 3     | Manager1   | 4     | 2         | 000101 | Executive1   |
| 3     | Manager2   | 5     | 2         | 000102 | Executive1   |
| 3     | Manager3   | 6     | 3         | 000201 | Executive2   |
| 3     | Manager4   | 7     | 99        | 000202 | WrongManager |
+----------------------------------------------------------------+

所以,我想添加一个条件,检查一个人的经理ID是否作为上述级别的id存在。例如,在第3级中,经理4的经理ID为99.经理ID 99在第2级不存在为人的身份,因此不应包括在内。

这是我对代码的尝试:

select 
    1 as level
    ,reportfor.preferredname + ' ' + reportfor.surname as PersonName
    ,id
    ,null as ManagerID
    ,emp.code as Code
    ,null as ManagerName
from d_edr edr
    inner join o_training_courses crs on crs.sap_course_num=edr.course_id
    inner join employees emp on emp.empid=edr.empid
    inner join employees reportfor on reportfor.code = '00'
group by 
    ,reportfor.preferredname + ' ' + reportfor.surname 
    ,id
    ,emp.code 
union 
select 
    2 as level
    ,reportfor.preferredname + ' ' + reportfor.surname as PersonName
    ,id
    ,emp.mgrid as ManagerID
    ,emp.code as Code
    ,mgr.preferredname + ' ' + mgr.surname as ManagerName
from d_edr edr
    inner join o_training_courses crs on crs.sap_course_num=edr.course_id
    inner join employees emp on emp.empid=edr.empid
    inner join employees reportfor on reportfor.code LIKE '00__'
    inner join employees mgr on mgr.empid=reportfor.mgrid
group by 
    ,reportfor.preferredname + ' ' + reportfor.surname
    ,id
    ,emp.mgrid
    ,emp.code
    ,mgr.preferredname + ' ' + mgr.surname
union 
select 
    3 as level
    ,reportfor.preferredname + ' ' + reportfor.surname as PersonName
    ,id
    ,emp.mgrid as ManagerID
    ,emp.code as Code
    ,mgr.preferredname + ' ' + mgr.surname as ManagerName
from d_edr edr
    inner join o_training_courses crs on crs.sap_course_num=edr.course_id
    inner join employees emp on emp.empid=edr.empid
    inner join employees reportfor on reportfor.code LIKE '00____'
    inner join employees mgr on mgr.empid=reportfor.mgrid
group by 
    ,reportfor.preferredname + ' ' + reportfor.surname
    ,id
    ,emp.mgrid
    ,emp.code
    ,mgr.preferredname + ' ' + mgr.surname

我希望这行代码可以解决它,但它不会

inner join employees mgr on mgr.empid=reportfor.mgrid

员工表的定义是:

empid = employee id
preferred name = first name
surname = last name 
code = hierarchy code
mgrid = manager id

2 个答案:

答案 0 :(得分:1)

使用CTE

WITH OrgChart AS    
(    
    SELECT  1 as level
            ,emp.preferredname + ' ' + emp.surname as PersonName
            ,id
            ,null as ManagerID
            ,emp.code as Code
            ,null as ManagerName
    FROM d_edr edr
        inner join o_training_courses crs on crs.sap_course_num=edr.course_id
        inner join employees emp on emp.empid=edr.empid
    WHERE emp.code = '00'

    UNION ALL

    SELECT OrgChart.level + 1 level
            ,emp.preferredname + ' ' + emp.surname as PersonName
            ,id
            ,null as ManagerID
            ,emp.code as Code
            ,null as ManagerName
    FROM d_edr edr
        inner join o_training_courses crs on crs.sap_course_num=edr.course_id
        inner join employees emp on emp.empid=edr.empid
        INNER JOIN OrgChart ON edr.empid = OrgChart.empid
    WHERE emp.code != '00'

)
SELECT *
FROM OrgChart;

答案 1 :(得分:0)

不确定这是否是您正在寻找的答案,但它可能是您为每个级别选择数据而非UNION的替代解决方案。

WITH Employee_hierarchy (Level, PersonName, EmpID, ManagerID, Code, ManagerName) AS
(

      SELECT 1 AS Level, base.PersonName, base.EmpID, base.mgrid, Code, convert(varchar(50), Null) ManagerName
      FROM employees base
      WHERE base.mgrid is null
      UNION all

      SELECT LEVEL + 1 AS Level, child.PersonName,  child.EmpID, child.mgrid, child.Code, eh.PersonName
      FROM employees child
      inner join Employee_hierarchy eh on child.mgrid = eh.EmpID
)     

Select * from Employee_hierarchy 

如果您想了解Common Table Expressions或CTE。这是一个链接 http://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx