1、邻接表(Adjacency List)

  • 实例:现在有一个要存储一下公司的人员结构,大致层次结构如下:

那么怎么存储这个结构?并且要获取以下信息:

  • 1.查询小天的直接上司。
  • 2.查询老宋管理下的直属员工。
  • 3.查询小天的所有上司。
  • 4.查询老王管理的所有员工。
 方案一、(Adjacency List)只存储当前节点的父节点信息。
-- -- MySQL树结构 --
-- Author: xielong Email:cnxielong@gmail.com -- -- 建表 --
DROP TABLE IF EXISTS Employees; CREATE TABLE IF NOT EXISTS Employees (
id INT AUTO_INCREMENT,
ename VARCHAR (),
job VARCHAR (),
parent_id INT,
PRIMARY KEY(id)
) ENGINE = INNODB DEFAULT CHARSET = UTF8; DESCRIBE Employees -- 插入数据 --
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('老王','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('老宋','产品部主管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('老牛','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('小吴','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('小李','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('小欢','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('小小','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('小天','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('肖丽','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('十号','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('十一号','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('十二号','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('十三号','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('十四号','高管','');
INSERT INTO `employees` ( `ename`, `job`, `parent_id`) VALUES('小黑十五','高管','');

数据库结构信息:

  • 好的,现在开始进入回答环节:

  • 1.查询小天的直接上司:
        -- 查询小天的上级Id  隐式内连接 关键条件父节点 --
    SELECT e2.id, e2.ename, e2.job FROM Employees e1, Employees e2 WHERE e1.`parent_id` = e2.id AND e1.id= -- 查询小天的上级Id 显示内连接 关键条件父节点 --
    SELECT e2.id, e2.ename, e2.job FROM Employees e1 INNER JOIN Employees e2 WHERE e1.`parent_id` = e2.id AND e1.id=

2.查询老宋管理下的直属员工:

  -- 查询老宋管理下的直属员工:隐式内连接 关键条件父子节点 老宋ID= --
SELECT e2.id, e2.ename, e2.job FROM Employees e1, Employees e2 WHERE e1.id= AND e2.`parent_id` = e1.id -- 查询小天的上级Id 显示内连接 关键条件父子节点 老宋.ename='老宋' --
SELECT e2.id, e2.ename, e2.job FROM Employees e1 INNER JOIN Employees e2 WHERE e2.`parent_id` = e1.id AND e1.ename='老宋'

3.查询小天的所有上司。

  • 这里肯定没法直接查,只能用循环进行循环查询,先查直接上司,再查直接上司的直接上司,依次循环,这样麻烦的事情,还是得先建立一个存储过程:
  • 睁大眼睛看仔细了,接下来是骚操作环节:
 --  、查询小天的所有上级 --

 -- 删除 --
DROP FUNCTION IF EXISTS getSuperiors; -- 创建 --
DELIMITER $$ CREATE DEFINER=`root`@`localhost` FUNCTION `getSuperiors` (`uid` INT) RETURNS VARCHAR()
BEGIN
DECLARE superiors VARCHAR() DEFAULT '';
DECLARE sTemp INTEGER DEFAULT uid;
DECLARE tmpName VARCHAR(); WHILE (sTemp>) DO
SELECT parent_id INTO sTemp FROM employees WHERE id = sTemp;
SELECT ename INTO tmpName FROM employees WHERE id = sTemp;
IF(sTemp>)THEN
SET superiors = CONCAT(tmpName,',',superiors);
END IF;
END WHILE;
SET superiors = LEFT(superiors,CHARACTER_LENGTH(superiors)-);
RETURN superiors;
END $$ -- 调用 --
SELECT getSuperiors() 上司;
  • 这一段存储过程可以查询子节点的所有父节点,来试验一下 

  • 好的,骚操作完成。

  • 显然,这样。获取子节点的全部父节点的时候很麻烦。。

4.查询老王管理的所有员工。

  思路如下:先获取所有父节点为老王id的员工id,然后将员工姓名加入结果列表里,在调用一个神奇的查找函数,即可进行神奇的查找:

   --  查询老王管理的所有员工 --

 -- 删除 --
DROP PROCEDURE IF EXISTS getSubordinate -- 创建 --
DELIMITER $$ CREATE DEFINER = `root` @`localhost` FUNCTION `getSubordinate` (`uid` INT) RETURNS VARCHAR ()
BEGIN
DECLARE str VARCHAR ();
DECLARE cid VARCHAR ();
DECLARE result VARCHAR ();
DECLARE tmpName VARCHAR ();
SET str = '$';
SET cid = CAST(uid AS CHAR());
WHILE
cid IS NOT NULL DO
SET str = CONCAT(str, ',', cid);
SELECT GROUP_CONCAT(id) INTO cid FROM employees WHERE FIND_IN_SET(parent_id, cid);
END WHILE;
SELECT
GROUP_CONCAT(ename) INTO result FROM employees WHERE FIND_IN_SET(parent_id, str);
RETURN result;
END $$ -- 调用 --
SELECT getSubordinate()

看神奇的结果:

 

  • 虽然搞出来了,但说实话,真是不容易。。。

  • 这种方法的优点是存储的信息少,查直接上司和直接下属的时候很方便,缺点是多级查询的时候很费劲。所以当只需要用到直接上下级关系的时候,用这种方法还是不错的,可以节省很多空间。

2、继承关系驱动的设计表和基于左右值编码的设计

参考链接: https://blog.csdn.net/lj1314ailj/article/details/52074216

参考:MySQL 实现树形的遍历

MySQL 实现树形的遍历(关于多级菜单栏以及多级上下部门的查询问题)

参考链接: https://blog.csdn.net/mchdba/article/details/39277301 ---------------------

MySQL树形结构的数据库表设计和查询的更多相关文章

  1. 树形结构的数据库表Schema设计-基于左右值编码

    树形结构的数据库表Schema设计 程序设计过程中,我们常常用树形结构来表征某些数据的关联关系,如企业上下级部门.栏目结构.商品分类等等,通常而言,这些树状结构需要借助于数据库完 成持久化.然而目前的 ...

  2. 树形结构的数据库表Schema设计

    今天又有幸遇到一个不知道的东西,那就是树型结构在数据库表中设计的问题.由于只是阅读了人家的东西,就直接给连接吧. 第一个:http://blog.csdn.net/monkey_d_meng/arti ...

  3. 数据库表设计时一对一关系存在的必要性 数据库一对一、一对多、多对多设计 面试逻辑题3.31 sql server 查询某个表被哪些存储过程调用 DataTable根据字段去重 .Net Core Cors中间件解析 分析MySQL中哪些情况下数据库索引会失效

    数据库表设计时一对一关系存在的必要性 2017年07月24日 10:01:07 阅读数:694 在表设计过程中,我无意中觉得一对一关系觉得好没道理,直接放到一张表中不就可以了吗?真是说,网上信息什么都 ...

  4. Innodb IO优化 — 数据库表设计 转

    数据库表设计这块学问比较多,我这里单从互联网角度出发同时结合Innodb的特性给出一些设计方法供大家参考.本文构建大概分两分部分:Innodb的特性及设计中如何利用这种特性. Innodb特性: In ...

  5. MySQL 树形结构 根据指定节点 获取其所在全路径节点序列

    背景说明 需求:MySQL树形结构, 根据指定的节点,获取其所在全路径节点序列. 问题分析 1.可以使用类似Java这种面向对象的语言,对节点集合进行逻辑处理,获取全路径节点序列. 2.直接自定义My ...

  6. MySQL 树形结构 根据指定节点 获取其所有父节点序列

    背景说明 需求:MySQL树形结构, 根据指定的节点,获取其所有父节点序列. 问题分析 1.可以使用类似Java这种面向对象的语言,对节点集合进行逻辑处理,获取父节点. 2.直接自定义MySQL函数  ...

  7. MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)

    背景说明 需求:MySQL树形结构, 根据指定的节点,获取其下属的所有子节点(包含路径上的枝干节点和叶子节点) 枝干节点:如果一个节点下还有子节点,则为枝干节点. 叶子节点:如果一个节点下不再有子节点 ...

  8. MySQL 树形结构 根据指定节点 获取其所有叶子节点

    背景说明 需求:MySQL树形结构, 根据指定的节点,获取其下属的所有叶子节点. 叶子节点:如果一个节点下不再有子节点,则为叶子节点. 问题分析 1.可以使用类似Java这种面向对象的语言,对节点集合 ...

  9. Oracle数据库表设计时的注意事项

    表是Oracle数据库中最基本的对象之一.万丈高楼从平地起,这个基础对象对于数据库来说,非常重要.因为其设计是否合理,直接跟数据库的性能相关.从Oracle数据库菜鸟到数据库专家这个过程中,在表设计与 ...

随机推荐

  1. Ubuntu下查看硬盘分区UUID的方法&所有Linux目录樹

    在Ubuntu中UUID的两种获取方法,至于UUID是什么,你可以大概理解为分区的标识符,像条形码那样. 在终端中输入下面的命令就可心查看到分区UUID了.命令1.sudo blkid 命令2.ls ...

  2. 蓝桥杯 乘积最大(区间dp、数据水的话long long,暴力就能过)

    Description 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋 ...

  3. android viewgrop(实现了事件监听/手动滑动)

    package com.example.myviewgroup; import android.content.Context;import android.os.Handler;import and ...

  4. index|substr

    #!/usr/bin/perl use strict; use warnings; $_ = 'duwanxkm,c.,df;oq123@#!@%$#^'; my $d ='d';my $o = 'o ...

  5. mysql免安装版 win10

    1.在官网中下载免安装版:https://dev.mysql.com/downloads/mysql/ 2.解压下载后的文件,新建 data 文件夹和 my.ini 文件  3.打开 my.ini 文 ...

  6. Q_Go2

    一.变量 1.1 变量的概念 变量是计算机语言中存储数据的抽象概念.变量的功能是存储数据.变量通过变量名访问. 变量的本质是计算机分配的一小块内存,专门用于存放指定数据,在程序运行过程中该数值可以发生 ...

  7. D - Association for Control Over Minds Kattis - control (并查集+STL)

    You are the boss of ACM (Association for Control over Minds), an upstanding company with a single go ...

  8. day09-正侧表达式

    while True: phone_num = input('please input your phone_num:') if len(phone_num) == 11 \ and phone_nu ...

  9. An internal error occurred during: "Redeploy".

    原因:项目中JDK使用的版本与现在使用的JDK版本不同所致. 解决方法:右键选择项目>properties>java Build Path>Libraries 查看下面的JRE Sy ...

  10. Windows2012R2 设置NTP时间服务器

    一.服务端配置 (Ntp服务器,客户端将根据这台服务器的时间进行同步) 1.微软键+R键,进入“运行”,输入“regedit”,进入注册表 2. HKEY_LOCAL_MACHINE\SYSTEM\C ...