注:テストデータベースのバージョンはMySQL8.0です。
scottユーザーがテーブルを作成してデータステートメントを入力する必要がある場合は、以下を参照してください:
scott createtablesおよびenterdatasqlスクリプト
1.需要
特定の行が属するノードのタイプ(リーフノード、ブランチノード、ルートノード)を決定します。
この例では、リーフノードは従業員がマネージャーではないことを示しています。ブランチノードの従業員はマネージャーであり、マネージャーのあるルートノードはマネージャーのない従業員です。
1(TRUE)または0(FALSE)を返すことにより、
2.解決策
EMPテーブルはツリー階層モデルであり、再帰階層モデルではなく、ルートノードのmgr値がnullであることに注意してください。
empが再帰的階層モデルである場合、ルートノードには自己参照が必要です(つまり、従業員KINGのmgr値はKINGのempnoになります)。
実際、自己参照は直感的ではないため、ここではルートノードのmgrがnull値に設定されています。
再帰的階層モデルでconnectby(Oracle)またはwithを使用する場合は、注意してください。SQLには無限ループがある可能性があります。再帰的階層を使用する必要がある場合は、コードでそのようなループを回避することを検討する必要があります。
select e.ename,
(select sign(count(*)) from emp d
where 0 =
(select count(*) from emp f
where f.mgr = e.empno)) as is_leaf,
(select sign(count(*)) from emp d
where d.mgr = e.empno
and e.mgr is not null) as is_branch,
(select sign(count(*)) from emp d
where d.empno = e.empno
and d.mgr is null) as is_root
from emp e
order by 4 desc,3 desc;
テスト記録:
mysql> select e.ename,
-> (select sign(count(*)) from emp d
-> where 0 =
-> (select count(*) from emp f
-> where f.mgr = e.empno)) as is_leaf,
-> (select sign(count(*)) from emp d
-> where d.mgr = e.empno
-> and e.mgr is not null) as is_branch,
-> (select sign(count(*)) from emp d
-> where d.empno = e.empno
-> and d.mgr is null) as is_root
-> from emp e
-> order by 4 desc,3 desc;
+--------+---------+-----------+---------+
| ename | is_leaf | is_branch | is_root |
+--------+---------+-----------+---------+
| KING | 0 | 0 | 1 |
| JONES | 0 | 1 | 0 |
| BLAKE | 0 | 1 | 0 |
| CLARK | 0 | 1 | 0 |
| SCOTT | 0 | 1 | 0 |
| FORD | 0 | 1 | 0 |
| SMITH | 1 | 0 | 0 |
| ALLEN | 1 | 0 | 0 |
| WARD | 1 | 0 | 0 |
| MARTIN | 1 | 0 | 0 |
| TURNER | 1 | 0 | 0 |
| ADAMS | 1 | 0 | 0 |
| JAMES | 1 | 0 | 0 |
| MILLER | 1 | 0 | 0 |
+--------+---------+-----------+---------+
14 rows in set (0.00 sec)