2017-06-07 6 views
0

私はemployeesというテーブルを持っています。すべての従業員が上司であるため誰にも報告しない従業員以外のすべての従業員を上司に報告します。MySQL - 最高の従業員に達するまで従業員の上司を見つけてください

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

特定の従業員の上司であるすべての従業員の従業員番号を表示できます。 (つまり、彼が報告する人、その人が報告する従業員、など)

employeeNumber 1165私は、クエリを実行するMySQLの文を書いたが、私は、これは読んで理解するために少し複雑すぎると考えてい

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

が得られるはずです:

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

を得るまであなたはので、私ドンここに..すべての親を取得するには非常に多くの似たようなケースをCTE再帰クエリを使用することができます

ループを手助けする必要があります – maSTAShuFu

+0

@maSTAShuFu、再帰CTEはまだ開発中のMySQLバージョン8.0までサポートされていません。 –

+0

私は@BillKarwinを参照してください...よくループと一時テーブルがあなたを助けるはずです – maSTAShuFu

答えて

0

Percona Live April 2017のMySQLで再帰的クエリに関するプレゼンテーションを行ったばかりです。簡単な答えは、バージョン8.0より前のMySQLでは簡単な解決策がないことです。 GAをもう1年ほどかかります)。

ジョインを使用して祖先ノードを取得できますが、固定数のジョインしか実行できません。階層の深さを予測することはできません。

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または私の過去のスタックオーバーフローの答えはWhat is the most efficient/elegant way to parse a flat table into a tree?

私の本のSQL Antipatterns: Avoiding the Pitfalls of Database Programmingの再帰的なクエリの方法についても書いています。

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が再帰クエリをサポートしていないことを知らなかった(ストアドプロシージャでさえも?)。 これは私の答えを無視しても安全です:(。

+0

再帰ストアドプロシージャを作成することができ、procの各呼び出しは独自のクエリを実行しますが、それは返す単一の再帰クエリとは異なります祖先の完全なセットの単一の結果セット。しかし、実際にはMySQLストアドプロシージャを使うべきではありません。彼らは吸う。 –

0

whileループでユーザー定義関数を使用することを検討してください。ループが停止値(たぶん0?)に達するまで繰り返され、udfが戻りますselect句に組み込むことができる単一のスカラー。

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 [email protected]; 

    select @parent:=reportsto from mytable where [email protected]; 

end while; 

select * from mytemp; 

drop table mytable;  
drop table mytemp; 

END; 
関連する問題