美文网首页
MySQL 创建表的分层视图

MySQL 创建表的分层视图

作者: 只是甲 | 来源:发表于2021-02-25 13:50 被阅读0次

备注:测试数据库版本为MySQL 8.0

如需要scott用户下建表及录入数据语句,可参考:
scott建表及录入数据sql脚本

一.需求

返回一个结果集,它描述整个表的层次。
在EMP表中,员工KING没有经理,所以KING是根节点。
从KING开始,显示KING下面的所有员工以及KING下属的所有员工(如存在)。

最后,返回下列结果集:
+------------------------------+
| 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.1 使用union和多个自联接

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;

测试记录:

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递归方法

可以看到MySQL 8.0开始支持的with递归,可以让代码大大简便,代码逻辑看起来也更有层次。

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

测试记录

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)

相关文章

  • MySQL 创建表的分层视图

    备注:测试数据库版本为MySQL 8.0 如需要scott用户下建表及录入数据语句,可参考:scott建表及录入数...

  • MySQL的视图

    MySQL的视图 创建基础表 视图的测试 视图的分类 单源表视图:视图的数据可以只取自一个基本表的部分行、列,这样...

  • MySQL 指南(二)

    本篇文章继续沿用 MySQL 指南(一) 中创建的 student 和 address 表。 视图为什么创建视图?...

  • 视图

    视图1,虚拟表,mysql5.1版本出现的特性,是通过表动态的生成的数据。创建视图CREATE VIEW <视图名...

  • 视图

    视图虚拟表,和普通表一样使用Mysql5.1的新特性,通过普通表动态生成的数据 一、创建视图create view...

  • DDL 数据库视图定义

    创建视图 根据表的查询结果创建视图 创建简单视图,由一张表的查询生成的视图 创建复杂视图,由多张表的查询或有函数时...

  • MySQL--索引

    MySQL索引 查看索引 创建索引 创建唯一索引 创建主键索引 删除索引 删除主键 MySQL视图 创建视图 删除...

  • Mysql学习——数据库基础操作(1)

    Mysql创建数据库Mysql删除数据库Mysql创建表Mysql删除表Mysql添加表数据Mysql修改表数据M...

  • 数据库

    一、MySQL中视图与表的区别 1.1 MySQL中视图和表的区别以及联系 视图是已经编译好的SQL语句,是基于S...

  • 推荐收藏 —— MySQL视图详细介绍

    前言: 在MySQL中,视图可能是我们最常用的数据库对象之一了。那么你知道视图和表的区别吗?你知道创建及使用视图要...

网友评论

      本文标题:MySQL 创建表的分层视图

      本文链接:https://www.haomeiwen.com/subject/dfiamktx.html