我有一张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语句来获得相同的结果?
答案 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;