MySQL - 继续找到员工的上级,直到达到最优秀的员工

时间:2017-06-07 22:05:59

标签: mysql sql recursive-query

我有一张employees表,其中所有员工都向上级报告,除了一名员工向其报告任何人,因为他是老板。

employeeNumber | reportsTo
---------------|-----------------
1002           | null
1056           | 1002
1143           | 1056
1165           | 1143
...

我希望能够显示所有员工的员工编号,这些员工是特定员工的上司。 (即他报告的人,以及该人报告的员工,......一路向上)

例如employeeNumber 1165应该产生

   | employeeNumber |
   |----------------|
   | null           |
   | 1002           |
   | 1056           |
   | 1143           |

我编写了一个执行查询的MySQL语句,但我认为这有点太复杂,无法阅读和理解:

select reportsTo as employeeNumber from employees where employeeNumber in
(select reportsTo from employees where employeeNumber in (select reportsTo from employees where
employeeNumber = 1165)) union select reportsTo from employees where employeeNumber in 
(select reportsTo from employees where employeeNumber = 1165) union select reportsTo from employees
where employeeNumber = 1165;

我可以用什么简单的MySQL语句来获得相同的结果?

4 个答案:

答案 0 :(得分:0)

我刚刚在2017年4月的Percona Live上发表了有关MySQL中递归查询的演示文稿。简短的回答是,在版本8.0之前,MySQL中没有简单的解决方案(我写这篇文章时仍在开发中,而不是预计将在一年左右的时间内成为GA。

您可以执行连接以获取祖先节点,但是您只能执行固定数量的连接,而无法预测层次结构的深度。

SELECT 
  e1.employeeNumber AS emp1,
  e2.employeeNumber AS emp2,
  e3.employeeNumber AS emp3,
  e4.employeeNumber AS emp4,
  e5.employeeNumber AS emp5,
  e6.employeeNumber AS emp6
FROM employees AS e1
LEFT JOIN employees AS e2 ON e1.reportsTo = e2.employeeNumber
LEFT JOIN employees AS e3 ON e2.reportsTo = e3.employeeNumber
LEFT JOIN employees AS e4 ON e3.reportsTo = e4.employeeNumber
LEFT JOIN employees AS e5 ON e4.reportsTo = e5.employeeNumber
LEFT JOIN employees AS e6 ON e5.reportsTo = e6.employeeNumber
WHERE e1.employeeNumber = 1165

在MySQL中查询分层数据还有其他几种解决方法,但它们都要求您以不同方式存储层次结构数据。您可能希望我的演示文稿Recursive Query Throwdown或我之前的Stack Overflow回答What is the most efficient/elegant way to parse a flat table into a tree?

我还在我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming中写过关于递归查询的方法。

答案 1 :(得分:0)

我已经写了一段时间了,因为我编写了实际的SQL代码(感谢Enitity Framework),所以我会尝试用伪代码写一下这可能会倾向于C#。对不起。 也许有人可以为我翻译一下?

int EmployeeNumber = 1165;
int bigChiefNumber = GetChiefOf(EmployeeNumber);

private int GetChiefOf(int EmployeeNumber)
{
    if(employeeNumber.reportsTo == null)
    {
        return employeeNumber;
    } else
    { 
        return GetChiefOf(employeeNumber.reportsTo);
    }
}

或稍短:

int BigChiefNumber = GetChiefOf(1165);

private int GetChiefOf(int employeeNumber)
{
    return (employeeNumber.reportsTo == null) 
        ? employeeNumber 
        : GetChiefOf(employeeNumber.reportsTo);
}

我想在SQL中你需要创建一个嵌套的存储过程。 我希望这能为你找到正确的方向:)。

编辑:所以,我没有注意到MySQL部分。我习惯了TSQL。我不知道MySQL不支持递归查询(甚至不支持存储过程?)。 这意味着您可以放心地忽略我的答案:(。

答案 2 :(得分:0)

可能要考虑使用带有while循环的用户定义函数。循环将递归,直到它达到一个停止值(可能是0?),并且udf将返回一个可以合并到select子句中的单个标量。

答案 3 :(得分:0)

此程序可以帮助您

循环,直到获得NULL高级和临时表

CREATE PROCEDURE GetList(me int)
BEGIN



create table mytable (id int, reportsto int);

create table mytemp  (id int);

insert into mytable 
values 
(1002, NULL ),
(1056, 1002 ),
(1143, 1056 ),
(1165, 1143 );


set @parent:=me;

insert into mytemp
values (@parent);

WHILE @parent IS NOT NULL DO

  insert into mytemp
  select reportsto from mytable where id=@parent;

  select @parent:=reportsto  from mytable where id=@parent;

end while;

select * from mytemp;

drop table mytable;    
drop table mytemp;

END;