MySQL creates a hierarchical view of the table

Note: The test database version is MySQL 8.0

If you need scott users to create tables and enter data statements, please refer to:
scott create tables and enter data sql scripts

1. Demand

Return a result set, which describes the hierarchy of the entire table.
In the EMP table, employee KING has no manager, so KING is the root node.
Starting from KING, all employees under KING and all employees under KING (if any) are displayed.

最后,返回下列结果集:
±-----------------------------+
| emp_tree |
±-----------------------------+
| KING |
| KING - BLAKE |
| KING - BLAKE - ALLEN |
| KING - BLAKE - JAMES |
| KING - BLAKE - MARTIN |
| KING - BLAKE - TURNER |
| KING - BLAKE - WARD |
| KING - CLARK |
| KING - CLARK - MILLER |
| KING - JONES |
| KING - JONES - FORD |
| KING - JONES - FORD - SMITH |
| KING - JONES - SCOTT |
| KING - JONES - SCOTT - ADAMS |
±-----------------------------+

2. Solution

2.1 Use union and multiple self-joins

select  emp_tree
  from  (
select  ename as emp_tree
  from  emp
 where  mgr is null
union
select concat(a.ename,' - ',b.ename)
  from emp a
 inner join emp b 
    on a.empno = b.mgr
where   a.mgr is null
union
select  concat(a.ename,' - ',
               b.ename,' - ',c.ename)
  from  emp a
 inner  join emp b
    on  a.empno = b.mgr
  left  join emp c
    on  b.empno = c.mgr
 where  a.ename = 'KING'
union
select  concat(a.ename,' - ',b.ename,' - ',
               c.ename,' - ',d.ename)
  from  emp a
  inner join emp b 
     on a.emono = b.mgr
  inner join emp c
     on b.emono = c.mgr
   left join emp d
     on c.empno = d.mgr
 where  a.ename = 'KING'
    ) x
 where tree is not null
 order by 1;

Test Record:

mysql> select  emp_tree
    ->   from  (
    -> select  ename as emp_tree
    ->   from  emp
    ->  where  mgr is null
    -> union
    -> select concat(a.ename,' - ',b.ename)
    ->   from emp a
    ->  inner join emp b
    ->     on a.empno = b.mgr
    -> where   a.mgr is null
    -> union
    -> select  concat(a.ename,' - ',
    ->                b.ename,' - ',c.ename)
    ->   from  emp a
    ->  inner  join emp b
    ->     on  a.empno = b.mgr
    ->   left  join emp c
    ->     on  b.empno = c.mgr
    ->  where  a.ename = 'KING'
    -> union
    -> select  concat(a.ename,' - ',b.ename,' - ',
    ->                c.ename,' - ',d.ename)
    ->   from  emp a
    ->   inner join emp b
    ->      on a.empno = b.mgr
    ->   inner join emp c
    ->      on b.empno = c.mgr
    ->    left join emp d
    ->      on c.empno = d.mgr
    ->  where  a.ename = 'KING'
    ->     ) x
    ->  where emp_tree is not null
    ->  order by 1;
+------------------------------+
| emp_tree                     |
+------------------------------+
| KING                         |
| KING - BLAKE                 |
| KING - BLAKE - ALLEN         |
| KING - BLAKE - JAMES         |
| KING - BLAKE - MARTIN        |
| KING - BLAKE - TURNER        |
| KING - BLAKE - WARD          |
| KING - CLARK                 |
| KING - CLARK - MILLER        |
| KING - JONES                 |
| KING - JONES - FORD          |
| KING - JONES - FORD - SMITH  |
| KING - JONES - SCOTT         |
| KING - JONES - SCOTT - ADAMS |
+------------------------------+
14 rows in set (0.00 sec)

2.2 with recursive method

You can see that with recursion, which MySQL 8.0 starts to support, can make the code much easier and the code logic looks more hierarchical.

with recursive emp2(ename,empno) AS
(
SELECT cast(ename as char(200)) ename,empno
  from emp
 where mgr is null
union ALL
SELECT concat(e2.ename,' - ',e1.ename) ,e1.empno
  from emp e1,emp2 e2
 where e1.mgr = e2.empno
)
select trim(ename) as ename
from emp2

Test Record

mysql> with recursive emp2(ename,empno) AS
    -> (
    -> SELECT cast(ename as char(200)) ename,empno
    ->   from emp
    ->  where mgr is null
    -> union ALL
    -> SELECT concat(e2.ename,' - ',e1.ename) ,e1.empno
    ->   from emp e1,emp2 e2
    ->  where e1.mgr = e2.empno
    -> )
    -> select trim(ename) as ename
    -> from emp2;
+------------------------------+
| ename                        |
+------------------------------+
| KING                         |
| KING - JONES                 |
| KING - BLAKE                 |
| KING - CLARK                 |
| KING - JONES - SCOTT         |
| KING - JONES - FORD          |
| KING - BLAKE - ALLEN         |
| KING - BLAKE - WARD          |
| KING - BLAKE - MARTIN        |
| KING - BLAKE - TURNER        |
| KING - BLAKE - JAMES         |
| KING - CLARK - MILLER        |
| KING - JONES - SCOTT - ADAMS |
| KING - JONES - FORD - SMITH  |
+------------------------------+
14 rows in set (0.00 sec)

Guess you like

Origin blog.csdn.net/u010520724/article/details/114078584