转载自:https://www.jb51.net/article/130222.htm

以下内容给大家介绍了MYSQL通过Adjacency List (邻接表)来存储树形结构的过程介绍和解决办法,并把存储后的图例做了分析(可以用来做权限控制)。

今天来看看一个比较头疼的问题,如何在数据库中存储树形结构呢?

像mysql这样的关系型数据库,比较适合存储一些类似表格的扁平化数据,但是遇到像树形结构这样有深度的人,就很难驾驭了。

举个栗子:现在有一个要存储一下公司的人员结构,大致层次结构如下:

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

1.查询小天的直接上司。

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

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

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

方案一、(Adjacency List)只存储当前节点的父节点信息。

CREATE TABLE `employees` (
`eid` int(11) NOT NULL,
`ename` varchar(255) DEFAULT NULL,
`position` varchar(255) DEFAULT NULL,
`parent_id` int(11) DEFAULT NULL,
PRIMARY KEY (`eid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

记录信息简单粗暴,那么现在存储一下这个结构信息:

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

1、查询小天的直接上司:

select e2.eid,e2.ename,e2.position
from employees e1,employees e2
where e1.parent_id=e2.eid and e1.ename = "小天";

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

SELECT e1.eid, e1.ename
FROM employees e1,employees e2
WHERE e1.parent_id = e2.eid
AND e2.ename = '老宋';

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

这里肯定没法直接查,只能用循环进行循环查询,先查直接上司,再查直接上司的直接上司,依次循环,这样麻烦的事情,还是得先建立一个存储过程:

睁大眼睛看仔细了,接下来是骚操作环节:

CREATE  FUNCTION `getSuperiors`(`uid` int) RETURNS varchar(1000)
BEGIN
DECLARE superiors VARCHAR(1000) DEFAULT '';
DECLARE sTemp INTEGER DEFAULT uid;
DECLARE tmpName VARCHAR(20);
WHILE (sTemp>0) DO
SELECT parent_id into sTemp FROM employees where eid = sTemp;
SELECT ename into tmpName FROM employees where eid = sTemp;
IF(sTemp>0)THEN
SET superiors = concat(tmpName,',',superiors);
END IF;
END WHILE;
SET superiors = LEFT(superiors,CHARACTER_LENGTH(superiors)-1);
RETURN superiors;
END

这一段存储过程可以查询子节点的所有父节点,来试验一下:

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

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

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

CREATE FUNCTION `getSubordinate`(`uid` int) RETURNS varchar(2000)
BEGIN
DECLARE str varchar(1000);
DECLARE cid varchar(100);
DECLARE result VARCHAR(1000);
SET str = '$';
SET cid = CAST(uid as char(10));
WHILE cid is not null DO
SET str = concat(str, ',', cid);
SELECT group_concat(eid) 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;

看神奇的结果:

公司架构:

CREATE DEFINER=`root`@`%` FUNCTION `findCompanyChildrens`(rootId INT) RETURNS varchar(4000) CHARSET utf8
BEGIN DECLARE sTemp VARCHAR (4000);
DECLARE sTempChd VARCHAR (4000); DECLARE sTempCount INT;
set sTempCount = 0;
SET sTemp = '$';
SET sTempChd = cast(rootId AS CHAR);
SET sTemp = CONCAT(sTemp, ',', sTempChd); WHILE sTempChd IS NOT NULL and sTempChd != 0 and sTempChd != 10 DO SELECT
count(1) INTO sTempCount
FROM
sp_company
WHERE is_deleted = 0 and FIND_IN_SET(parent_company_id, sTempChd) > 0; if sTempCount > 0 then
SELECT
group_concat(id) INTO sTempChd
FROM
sp_company
WHERE is_deleted = 0 and
FIND_IN_SET(parent_company_id, sTempChd) > 0; SET sTemp = CONCAT(sTemp, ',', sTempChd);
ELSE
SET sTempChd = 0;
end if; END
WHILE;
RETURN sTemp;
END
CREATE DEFINER=`root`@`%` FUNCTION `findCompanyRoot`(companyId INT) RETURNS int(11)
BEGIN DECLARE sTemp INT;
DECLARE sTempChd INT;
DECLARE sTempCount INT;
declare runCnt int;
set sTempCount = 0;
SET sTemp = 1;
SET sTempChd = companyId;
set runCnt = 0; WHILE sTempChd is not null and sTempChd != 0 and sTempChd != 1 and sTempChd != 10 and runCnt < 5 DO SET sTemp = sTempChd;
set runCnt = runCnt +1; SELECT
count(1) INTO sTempCount
FROM
sp_company
WHERE is_deleted = 0 and id = sTempChd; if sTempCount > 0 then
SELECT
parent_company_id INTO sTempChd
FROM
sp_company
WHERE is_deleted = 0 and id = sTempChd;
ELSE
SET sTempChd = 1;
end if; END
WHILE;
RETURN sTemp;
END

Mysql通过Adjacency List(邻接表)存储树形结构的更多相关文章

  1. DS实验题 Old_Driver UnionFindSet结构 指针实现邻接表存储

    题目见前文:DS实验题 Old_Driver UnionFindSet结构 这里使用邻接表存储敌人之间的关系,邻接表用指针实现: // // main.cpp // Old_Driver3 // // ...

  2. 图的邻接表存储表示(C)

    //---------图的邻接表存储表示------- #include<stdio.h> #include<stdlib.h> #define MAX_VERTEXT_NUM ...

  3. 数据结构(11) -- 邻接表存储图的DFS和BFS

    /////////////////////////////////////////////////////////////// //图的邻接表表示法以及DFS和BFS //////////////// ...

  4. 邻接表存储图,DFS遍历图的java代码实现

    import java.util.*; public class Main{ static int MAX_VERTEXNUM = 100; static int [] visited = new i ...

  5. 图的邻接表存储 c实现

    图的邻接表存储 c实现 (转载) 用到的数据结构是 一个是顶点表,包括顶点和指向下一个邻接点的指针 一个是边表, 数据结构跟顶点不同,存储的是顶点的序号,和指向下一个的指针 刚开始的时候把顶点表初始化 ...

  6. PTA 邻接表存储图的广度优先遍历(20 分)

    6-2 邻接表存储图的广度优先遍历(20 分) 试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(V ...

  7. 数据结构之---C语言实现图的邻接表存储表示

    // 图的数组(邻接矩阵)存储表示 #include <stdio.h> #include <stdlib.h> #include <string.h> #defi ...

  8. PTA 邻接表存储图的广度优先遍历

    试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(Vertex) ) 其中LGraph是邻接表存储的 ...

  9. HDU 4864 Task (贪心+STL多集(二分)+邻接表存储)(杭电多校训练赛第一场1004)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4864 解题报告:有n台机器用来完成m个任务,每个任务有一个难度值和一个需要完成的时间,每台机器有一个可 ...

随机推荐

  1. 本地数据库(sql server)插入一条新数据时,同步到服务器数据库

    之前有个同学问我,本地数据库插入新数据时怎么同步到服务器上,当时我先想到是程序逻辑控制,作相应的处理. 但有时候我们程序不太好处理,那能不能从数据库入手呢,数据库不是有触发器(Trigger)吗,应该 ...

  2. synchronized(this)、synchronized(class)与synchronized(Object)的区别

    在多线程开发中,我们经常看到synchronized(this).synchronized(*.class)与synchronized(任意对象)这几种类型同步方法.但是是否知道这几种写法有什么区别了 ...

  3. SpringMvc-reset风格

    reset风格就是不用加?或者&等等符号直接通过地址栏向后台发送数据的方法 rest风格是实现 1.需要在web.xml中配置一个filter <filter> <filte ...

  4. March 21 2017 Week 12 Tuesday

    Sometimes ever, sometimes never. 相聚有时,后会无期. Maybe love is something we can't touch but we can feel w ...

  5. js原型链继承及调用父类方法

    方法1: var Parent= function () { }; Parent.prototype.process = function(){ alert('parent method'); }; ...

  6. [原] Android自动打包之命令行打包

    Android自动打包流程详细图: 总结为以下几个步骤: 1. 生成R文件 2. Java代码编译成class文件 3. class文件生成dex文件 4. 打包资源 5. 生成apk 6. 创建密匙 ...

  7. libevent将信号封装为socket通知的核心代码

    #include"stdafx.h" #include"iostream" #include "algorithm" #include&qu ...

  8. react工程目录简介

    首先我们可以看到底部一个 yarn.lock的文件,这个文件主要是项目依赖的安装包,他的一些版本号,会在这里做一些限制,这个文件不要动就好了. readme.md,这个文件其实是项目的说明文件,他里面 ...

  9. CentOS6.6上进程挂起的诡异问题和处理

    由于新的服务器不再支持CentOS5.4系统了,我们在新装机器上安装CentOS6.6.随着CentOS6.6机器的增多,我们逐渐注意到一个诡异问题:运行在这些机器上的某些进程,容易莫名其妙地挂起(举 ...

  10. Go转json数组

    Go转json数组 最近因需要要调用gitlab的API,其中有一个是根据私有token获取Repositories列表 由于返回结果是一个json数组,单纯使用json.Unmarshal没法实现, ...