精华内容
下载资源
问答
  • 树状结构表结构和功能设计
    2022-02-17 15:47:38
    在我们开发过程中经常会遇到各种组织树结构,比如我们的公司人员结构,权限资源的管理,等等。而我们这些数据落到表里面是以一条条数据构成的,我们存储资源时按照一条条存储是非常简单的,但是在操作资源构建树的时候往往会碰到很多问题,下面我们以一条实例来探讨组织树资源的表结构设计和功能点。
    

    表结构设计(以mysql为基础)

    我们要设计一个树状结构的数据存储,第一反应是在表里面加一个parent_id
    这肯定没有错,我们通过数据的id和parent_id就能组装成整个的树结构,但是比如我们的需求往往不是这么简单,比如我需要关注节点的状态,根据状态去做图标的显示和功能的限制,那么我们就需要添加一个status字段
    同时我们的树不可能无限制构建,递归是一个非常消耗资源的事情,所以我们需要限制树的高度,这里我们可以通过加入一个level字段去控制树的层级
    也可能我们有这样的需求,我们关心节点之间的顺序,于是我们又要添加一个order_num来控制排序
    综合上述,我们得出一张这样的表结构

    字段名称字段类型字段描述是否唯一是否非空
    idint(11)主键
    parent_idint(11)父id
    leveltinyint(2)层级
    parent_pathvarchar(640)当前节点在树节点中的路径,以/分割,如0/1/2/
    namevarchar(255)名称
    statustinyint是否启用
    order_numint(5)顺序

    字段的用途大家都应该明白,但是这里有个parent_path有点迷糊,在树结构的环境下往往有这么个需求,查找某个节点的所有子节点,如此,按照一般思路我们需要递归去查询,对数据库造成的性能损失
    这里我们引入了parent_path字段,每次需要查询子节点的时候,只需要执行sql:

     SELECT id from tree_test where path like '0/1/2/%'
    

    当然还有一种思路是path按照逗号分割(0,1,2),这样我们可以直接使用mysql的内置函数FIND_IN_SET

    SELECT id from tree_test where FIND_IN_SET('1',path);
    

    但是,通过我们查看执行计划,like的方式可以走索引,而FIND_IN_SET不会走,所以我们选择like的方式。
    在这里插入图片描述
    你以为到这里就结束啦,当然没有,节点的顺序除了同节点间的交换插入,可能从其他层级进入当前层级,或者从当前层级扩散到其他层级,万物都是一把双刃剑,parent_path给我们带来方便的同时,我们每次在节点移动的时候需要变更这个path,增加了一定的工作量。
    那么我们在挪动节点的时候,顺序是怎么维护的呢?

    功能设计

    我整理了一个图,其中x表示元素的起始顺序,y表示元素的目标顺序,当我们在节点进行变更时需要按照一下规则维护order_num字段
    在这里插入图片描述
    以上就是我针对树状数据开发过程中可能遇到的点,如果还有需要解决的问题欢迎在评论区留言。

    更多相关内容
  • 昨天有人在QQ小组问起,无限分层的树状结构,数据量比较大,在一万条以上,如何设计数据库的结构。其实这是个老生常谈的问题,一般的做法是有一个 pid字段,为了提高效率,还会有个FullPath字段。(一些人还设置一个...
  • vue 实现自定义树状结构图 可动态添加、删除 可整体拖拽 如需内容也为动态,把组件内容使用input、select等组件替换 数据结构 treeData: [{ name: '1', child: [ { name: '2', child: [{ name: '1' }, { ...
  • 基于Vue-Ztree-2.0实现树状结构的展示 启动步骤: 1.cmd至前端项目根目录执行“npm install”命令 2.“npm start”命令启动项目 后端项目:tree 基于springboot、mybaits-plus、mysql实现树状结构 启动步骤: 1.mvn...
  • 传统的关系数据模型难以满足大数据应用日益丰富的数据表达和处理的需求,因此实践中涌现了多种非传统的大数据类型。...系统介绍了树状结构大数据类型,并探讨如何高效支持树状结构大数据的分析运算。
  • NULL 博文链接:https://zhangqkunkun.iteye.com/blog/788828
  • 树状结构插件 z-tree 功能强大, 便于操作树状结构插件 z-tree 功能强大, 便于操作树状结构插件 z-tree 功能强大, 便于操作树状结构插件 z-tree 功能强大, 便于操作
  • zTree 简介  zTree 是一个依靠 jQuery 实现的多功能 “树插件”。优异的性能、灵活的配置、多种功能的组合是 zTree 最大优点。  zTree 是开源免费的软件(MIT 许可证)。如果您对 zTree 感兴趣或者愿意资助 ...
  • ztree树状结构

    2018-07-10 21:16:35
    ztree树状结构,适合做层级结构,比如组织结构,商品种类
  • Sql Server 分级别显示树状结构表格 及显示各个父层有多少个子级数据,可用于部门树状图等。。。
  • 在项目中,我们经常会需要一些树状结构的样式来显示层级结构等,比如下图的样式,之前在学.net的时候可以直接拖个服务端控件过来直接使用非常方便。但是利用Jquery的一些插件,也是可以实现这些效果的,比如说Jquery...
  • 主要为大家详细介绍了C#使用Jquery zTree实现树状结构显示和异步数据加载,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 通过解析Json数据生成树状结构 1、使用newtonsoft.json解析json 2、无限级 3、父子节点联动
  • 内含exe文件 博文链接:https://hongyegu.iteye.com/blog/1179599
  • combo-tree是一款jQuery带多选和过滤功能的树状结构下拉框插件。通过该插件,可以在下拉框中生成指定数据结构的目录树,提供单选和多选,以及过滤功能。
  • 下拉列表以树状结构显示,实用.NET的C# WPF语音结构进行编写,界面简洁,适用作为一个窗体中的下拉控件实用。
  • 树状结构网络版

    2019-08-09 01:03:44
    NULL 博文链接:https://lanxs.iteye.com/blog/2175125
  • 有时候需要罗列下U盘等移动设备或一个程序下面的目录结构的需求。基于这样的需求个人整理了一个使用Python的小工具,期望对有这方面需求的朋友有所帮助。以下为具体代码: 如果你所有要求的文件目录不需要完整的文件...
  • 一个树状结构列表.zip

    2019-09-24 18:21:31
    一个树状结构列表。.zip,A view of the tree structure.树状结构列表。
  • 三部分树状结构图PPT素材.pptx,三部分树状结构图PPT,适用于总分关系等各种情况,可以用在课程介绍PPT中,产品演示PPT中,项目提案PPT中,标题分开又对应,树桩结构图形式新颖独特。
  • js实现树状结构

    2013-03-12 14:44:54
    用Dtree写的树状结构,代码解释详细。
  • recyclerView实现树状结构,带有header和footer,可以自己定义显示头或者不显示
  • NULL 博文链接:https://free0007.iteye.com/blog/1888485
  • 一个类,可以遍历一个目录,将该目录下所有文件以及子目录及其文件都遍历,生成一个层次分明的数组,还可以将遍历的结果生成一个树状的字符串,直接echo到浏览器。 |-|a.txt |-|b.txt |-|c目录 |---|d.txt |---|c1...
  • 增加系统调用,遍历系统当前所有进程的任务描述符,并将pid组织成树状结构显示,压缩包中包含源码和文档
  • oa组织机构(树状结构)

    2019-04-18 01:21:22
    NULL 博文链接:https://diaochenlong2.iteye.com/blog/1839715
  • 树状结构下拉选

    2015-09-15 08:19:31
    这是我在项目中用到非常不错的树状结构下拉选
  • 实现树状结构的两种方法更新时间:2006年10月09日 00:00:00 作者:实现树状结构的两种方法1。递归法递归是指在函数中显式的调用它自身。利用递归法实现树状结构的特点是写入数据速度较快,显示速度较慢(在树的分支/...

    实现树状结构的两种方法

    更新时间:2006年10月09日 00:00:00   作者:

    实现树状结构的两种方法

    1。递归法

    递归是指在函数中显式的调用它自身。

    利用递归法实现树状结构的特点是写入数据速度较快,显示速度较慢(在树的分支/层次较多的情况下尤其明显)。适用与写入数据量大,树的结构复杂的情况下。

    数据结构(以mysql为例)

    代码:--------------------------------------------------------------------------------

    CREATE TABLE `tree1` (

    `id` tinyint(3) unsigned NOT NULL auto_increment,

    `parentid` tinyint(3) unsigned NOT NULL default '0',

    `topic` varchar(50) default NULL,

    PRIMARY KEY  (`id`),

    KEY `parentid` (`parentid`)

    ) TYPE=MyISAM;

    INSERT INTO `tree1` (`id`, `parentid`, `topic`) VALUES

    (1,0,'树1'),

    (2,0,'树2'),

    (3,0,'树3'),

    (4,2,'树2-1'),

    (5,4,'树2-1-1'),

    (6,2,'树2-2'),

    (7,1,'树1-1'),

    (8,1,'树1-2'),

    (9,1,'树1-3'),

    (10,8,'树1-2-1'),

    (11,7,'树1-1-1'),

    (12,11,'树1-1-1-1');

    --------------------------------------------------------------------------------

    字段说明

    id,记录的id号

    parentid,记录的父记录id(为0则为根记录)

    topic,记录的显示标题

    显示程序

    顺序树:

    PHP代码:--------------------------------------------------------------------------------

    /* 数据库连接 */

    mysql_connect();

    mysql_select_db('tree');

    /* 树状显示的递归函数 */

    function tree($parentid = 0) {

    /*执行sql查询,获取记录的标题和id*/

    $sql = "select topic,id from tree1 where parentid = $parentid order by id asc";

    $rs = mysql_query($sql);

    /* 缩进*/

    echo("

    • ");

    while($ra = mysql_fetch_row($rs)) {

    /* 显示记录标题 */

    echo('

    '.$ra[0].'');

    /* 递归调用 */

    tree($ra[1]);

    }

    echo("

    ");

    }

    tree();

    ?>

    --------------------------------------------------------------------------------

    逆序树:

    PHP代码:--------------------------------------------------------------------------------

    /* 数据库连接 */

    mysql_connect();

    mysql_select_db('tree');

    /* 树状显示的递归函数 */

    function tree($parentid = 0) {

    /*执行sql查询,获取记录的标题和id*/

    $sql = "select topic,id from tree1 where parentid = $parentid order by id desc";

    $rs = mysql_query($sql);

    /* 缩进*/

    echo("

    • ");

    while($ra = mysql_fetch_row($rs)) {

    /* 显示记录标题 */

    echo('

    '.$ra[0].'');

    /* 递归调用 */

    tree($ra[1]);

    }

    echo("

    ");

    }

    tree();

    ?>

    --------------------------------------------------------------------------------

    插入数据程序

    PHP代码:--------------------------------------------------------------------------------

    /* 数据库连接 */

    mysql_connect();

    mysql_select_db('tree');

    $sql = "insert into tree (topic,parentid) values('树3-1',3);";

    mysql_query($sql);

    ?>

    --------------------------------------------------------------------------------

    2。排序字段法

    此方法是通过在数据结构中增加一个标志记录在整个树中的顺序位置的字段来实现的。特点是显示速度和效率高。但在单个树的结构复杂的情况下,数据写入效率有所不足。而且顺序排列时候,插入,删除记录的算法过于复杂,故通常用逆序排列。

    数据结构(以mysql为例)

    代码:--------------------------------------------------------------------------------

    CREATE TABLE `tree2` (

    `id` tinyint(3) unsigned NOT NULL auto_increment,

    `parentid` tinyint(3) unsigned NOT NULL default '0',

    `rootid` tinyint(3) unsigned NOT NULL default '0',

    `layer` tinyint(3) unsigned NOT NULL default '0',

    `orders` tinyint(3) unsigned NOT NULL default '0',

    `topic` varchar(50) default NULL,

    PRIMARY KEY  (`id`),

    KEY `parentid` (`parentid`),

    KEY `rootid` (`rootid`)

    ) TYPE=MyISAM

    INSERT INTO `tree2` (`id`, `parentid`, `rootid`, `layer`, `orders`, `topic`) VALUES

    (1,0,1,0,0,'树1'),

    (2,0,2,0,0,'树2'),

    (3,0,3,0,0,'树3'),

    (4,2,2,1,2,'树2-1'),

    (5,4,2,2,3,'树2-1-1'),

    (6,2,2,1,1,'树2-2'),

    (7,1,1,1,4,'树1-1'),

    (8,1,1,1,2,'树1-2'),

    (9,1,1,1,1,'树1-3'),

    (10,8,1,2,3,'树1-2-1'),

    (11,7,1,2,5,'树1-1-1'),

    (12,11,1,3,6,'树1-1-1-1');

    --------------------------------------------------------------------------------

    显示程序

    PHP代码:--------------------------------------------------------------------------------

    /* 数据库连接 */

    mysql_connect();

    mysql_select_db('tree');

    /* 选出所有根记录id */

    $sql = "select id from tree2 where parentid = 0 order by id desc";

    $rs = mysql_query($sql);

    echo("

    • ");

    $lay = 0;

    while($ra = mysql_fetch_row($rs)) {

    echo("

    • ");

    /* 选出此树所有记录,并按orders字段排序 */

    $sql = "select topic,layer from tree2 where rootid = $ra[0] order by orders";

    $rs1 = mysql_query($sql);

    while($ra1 = mysql_fetch_row($rs1)) {

    /* 缩进显示 */

    if($ra1[1]>$lay) {

    echo(str_repeat("

    • ",$ra1[1]-$lay));

    }elseif($ra1[1]

    echo(str_repeat("

    ",$lay-$ra1[1]));

    }

    /* 记录显示 */

    //echo("$ra1[1]>$lay");

    echo("

    $ra1[0]");

    $lay = $ra1[1];

    }

    echo("

    ");

    }

    echo("

    ");

    ?>

    --------------------------------------------------------------------------------

    插入数据程序

    PHP代码:--------------------------------------------------------------------------------

    /* 数据库连接 */

    mysql_connect();

    mysql_select_db('tree');

    /* 插入根记录 */

    $sql = "insert into tree2 (topic) values ('树5')";

    mysql_query($sql);

    $sql = "update tree2 set rootid = id where id = ".mysql_insert_id();

    mysql_query($sql);

    /* 插入子记录 */

    $parentid = 5;//父记录id

    /* 取出 根记录id,父记录缩进层次,父记录顺序位置 */

    $sql = "select rootid,layer,orders from tree2 where id = $parentid";

    list($rootid,$layer,$orders) = mysql_fetch_row(mysql_query($sql));

    /* 更新插入位置后记录的orders值 */

    $sql = "update tree2 set orders = orders + 1 where orders > $orders";

    mysql_query($sql);

    /* 插入记录 */

    $sql = "insert into tree2 (rootid,parentid,orders,layer,topic) values ($rootid,$parentid,".($orders+1).",".($layer+1).",'树2-1-1-2')";

    mysql_query($sql);?>

    相关文章

    1a1b05c64693fbf380aa1344a7812747.png

    域名查询代码公布...2006-10-10

    4f55910a645b073bc4fc65dc10dc14bd.png

    最令PHP初学者头痛的十四个问题...2006-09-09

    0ea3c7666119d5615e582f823fb3fad6.png

    一个高ai的分页函数和一个url函数...2006-10-10

    4f96a78db829b1556ff16de21e013c7a.png

    PHP 存取 MySQL 数据库的一个例子...2006-10-10

    8cc1031babc6aff2319f1c6af8544aa0.png

    对象中成员的访问(在一个对象的内部方法中,去访问本对轩昂中的其他方法和成员属性)2011-06-06

    0c932a99bb7b6f23c937db507070cc7b.png

    一个更简单的无限级分类菜单代码...2007-01-01

    cca732bf65a93ed2ec0ac80c638460fe.png

    挑战最棒的留言本的源码(五)...2006-10-10

    2d9f31f2af7b675a3d153d2b7f1035a7.png

    数组array是一组有序的变量,其中每个变量被叫做一个元素。2009-10-10

    b452cee8ec5cd9e58ab98eba17281e59.png

    简单介绍下 PHP5 中引入的 MYSQLI的用途...2007-03-03

    f4838ec7e2d4da28e0b57d4e852dadd4.png

    用PHP开发GUI...2006-10-10

    最新评论

    展开全文
  • JAVA树状结构数据处理

    2022-04-18 11:33:54
    在工作中遇到需要对树状结构的数据进行一个处理,通过本文做出一个分享和总结。本文对数据的查询主要是通过MyBatis在xml文件中使用resultMap标签来实现对数据的循环查询,并且通过返回值映射到VO中,通过VO中set方法...


    前言

    在工作中遇到需要对树状结构的数据进行一个处理,通过本文做出一个分享和总结。本文对数据的查询主要是通过MyBatis在xml文件中使用resultMap标签来实现对数据的循环查询,并且通过返回值映射到VO中,通过VO中set方法的处理直接生成一个树状对象。


    一、数据库中的结构

    在这里插入图片描述
    要处理的对象在数据库中大致是这样的格式,并未用到一个记录父级完整路径的一个键。
    例如:
    在这里插入图片描述
    若数据库中加了一个用来记录父级id的一个键,要查询二级分类及二级分类的所有下级分类则只需要对parent_order这个键进行模糊查询即可。

    二、查询步骤

    项目结构都差不多就不在这里赘述了,直接mapper类对应xml中的sql语句直接调用就是了。

    1.XML

    代码如下(示例):(下列代码只作参考,我没跑过的不一定对,大致结构是没有错的)

       <resultMap id="studyMainTree" type="com.cataloguemanage.business.entity.CatalogClassifyVO">
            <result column="id" property="id" javaType="String"/>
            <result column="parentId" property="parentId" javaType="String"/>
            <result column="name" property="name" javaType="String"/>   
            <collection column="id" property="children" select="getChildrenByPid"
    					ofType="com.cataloguemanage.business.entity.CatalogClassifyVO"/>
        </resultMap>
        
        <select id="queryClassify" resultMap="studyMainTree">
            SELECT
            id ,
            parent_id parentId ,
            name 
            FROM catalog_classify 
            WHERE parent_id ='0'
        </select>
        
        <select id="getChildrenByPid" resultMap="studyMainTree">
            SELECT
            id ,
            parent_id  parentId ,
            name 
            FROM catalog_classify 
            WHERE parent_id =#{id} 
        </select>
    

    queryClassify就是这个级联查询的入口 queryClassify执行一次 getChildrenByPid执行多次

    2.VO

    代码如下(示例):联系上图中的CatalogClassifyVO,使用CatalogClassifyVO来接受查询到的数据

    @Data
    public class CatalogClassifyVO  {
    	private String id;
    
    	private String name;
    	
    	private String parentId;
    
        public List<CatalogClassifyVO> getChildren() {
            return children;
        }
    
        public void setChildren(List<CatalogClassifyVO> children) {
            if (children!= null && !children.isEmpty()) {
            	//相应的业务逻辑
               this.children=children;
               }
        }
    
        //子分类
        private List<CatalogClassifyVO> children;
    }
    

    在VO中我们能通过在set方法中添加相应的业务逻辑,比如统计子分类的数量、整合某些字段等等,但所生成的树对象是单向的,只能从父找到子。父与子的联系都在setChildren方法中,并且是以类似递归一样从最下级的set方法开始执行。

    3.树中插入叶子

    在resultMap中再添加一个collection,并在VO中添加接受对应对象的成员。能实现对不同数据结构的对象进行查询,并组合成一个树状结构。
    XML

     <resultMap id="resourceList" type="com.cataloguemanage.business.entity.CatalogClassifyVO">
            <result column="classifyCode" property="classifyCode" javaType="String"/>
            <collection column="classifyCode" property="children" select="selectCatalogueChildren"
                        ofType="com.cataloguemanage.business.entity.CatalogClassifyVO"/>
            <collection column="classifyCode" property="resource" select="selectResourceByresourceCode"
                        ofType="java.util.Map"/>
        </resultMap>
        <select id="selectCatalogueInfo" resultMap="resourceList">
            SELECT
            a.classify_code classifyCode
            from
            catalog_classify a
            where
            a.classify_code=#{classifyCode} and  a.is_delete='0'
        </select>
        <select id="selectCatalogueChildren" resultMap="resourceList">
             SELECT
            a.classify_code classifyCode
            from
            catalog_classify a
            WHERE
            a.parent_id=#{classifyCode} and  a.is_delete='0'
        </select>
        <select id="selectResourceByResourceCode" resultType="java.util.Map">
            select
            b.resource_code resourceCode,
            b.resource_name label
            from catalog_resource_classify a left join catalog_resource b
            on b.resource_code = a.resource_classify_code
            where b.is_delete = '0'
            and b.status ='6'
            and a.classify_code = #{classifyCode}
        </select>
    

    VO

       private List<CatalogShareResource> resource =new ArrayList<>();
        
       public void setResource(List<CatalogShareResource> resource) {
            if(resource !=null&&!resource.isEmpty()){
                this.resource.addAll(resource);
            }
        }
    

    总结

    用映射来处理树状结构的数据是非常清晰的,不需要查询出所有数据来用多个for循环来进行遍历和数据组装。使用级联查询还是非常灵活的,例如能携带多个参数到子查询中实现树的模糊查询、在set方法中将所有的子整合成一个集合等等。在这次的工作中,我也需要对树的处理做了许多的定制化的需求,如果使用for来应对这些需求是很难完成任务的。而级联查询对数据库IO压力的是否过大我没有进行相关的查询验证。若数据量大还是推荐存进Redis中。
    第一次做分享,有问题请见谅。
    企鹅:747870530

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 112,522
精华内容 45,008
关键字:

树状结构

友情链接: 5183.zip