两个字段:

  • pid:父级ID
  • parent_ids:所有经过的路径节点ID

这样设计有个好处是,可以查任意节点的所有子节点,从任意节点开始既可以向上查,也可以向下查

select * from enterprise where find_in_set(4, parent_ids); 

构造菜单树(Java实现)

@Data
@NoArgsConstructor
public class Menu {
private Integer id;
private Integer pid; // 父菜单ID
private String pids; // 所有父菜单ID集合(按顺序,逗号分隔)
private String name;
private String code;
private int sort;
List<Menu> children; public Menu(Integer id, Integer pid, String name, int sort) {
this.id = id;
this.pid = pid;
this.name = name;
this.sort = sort;
}
}

第一种写法

@Test
void contextLoads() throws Exception {
List<Menu> allMenuList = new ArrayList<>();
allMenuList.add(new Menu(1, 0, "一级菜单A", 1));
allMenuList.add(new Menu(2, 0, "一级菜单B", 2));
allMenuList.add(new Menu(3, 1, "二级菜单AA", 1));
allMenuList.add(new Menu(4, 2, "二级菜单BB", 1));
allMenuList.add(new Menu(5, 3, "三级菜单AAA", 2));
allMenuList.add(new Menu(6, 4, "三级菜单BBB", 2));
allMenuList.add(new Menu(7, 1, "二级菜单AC", 2)); // 找到所有一级菜单
List<Menu> parentList = allMenuList.stream().filter(e->e.getPid().equals(0)).collect(Collectors.toList());
for (Menu menu : parentList) {
menu.setChildren(getChild(menu.getId(), allMenuList));
}
} /**
* 递归查找子菜单
*/
public List<Menu> getChild(Integer pid, List<Menu> allMenuList) {
List<Menu> childList = new ArrayList<>();
for (Menu menu : allMenuList) {
if (pid.equals(menu.getPid())) {
menu.setChildren(getChild(menu.getId(), allMenuList));
childList.add(menu);
}
}
childList.sort(Comparator.comparing(Menu::getSort).reversed());
return childList;
}

第二种写法

@Test
void contextLoads() throws Exception {
List<Menu> allMenuList = new ArrayList<>();
allMenuList.add(new Menu(1, 0, "一级菜单A", 1));
allMenuList.add(new Menu(2, 0, "一级菜单B", 2));
allMenuList.add(new Menu(3, 1, "二级菜单AA", 1));
allMenuList.add(new Menu(4, 2, "二级菜单BB", 1));
allMenuList.add(new Menu(5, 3, "三级菜单AAA", 2));
allMenuList.add(new Menu(6, 4, "三级菜单BBB", 2));
allMenuList.add(new Menu(7, 1, "二级菜单AC", 2)); // 第二种写法
List<Menu> list = allMenuList.stream()
.filter(e->e.getPid().equals(0))
.peek(e->e.setChildren(getChild2(e.getId(), allMenuList)))
.sorted(Comparator.comparing(Menu::getSort))
.collect(Collectors.toList());
} /**
* 递归查找子菜单(简写版)
*/
public List<Menu> getChild2(Integer pid, List<Menu> allMenuList) {
return allMenuList.stream()
.filter(e->pid.equals(e.getPid()))
.peek(e->e.setChildren(getChild2(e.getId(), allMenuList)))
.sorted(Comparator.comparing(Menu::getSort))
.collect(Collectors.toList());
}

MySQL树形结构表设计的更多相关文章

  1. Atitit.各种 数据类型 ( 树形结构,表形数据 ) 的结构与存储数据库 attilax 总结

    Atitit.各种  数据类型 ( 树形结构,表形数据  ) 的结构与存储数据库 attilax  总结 1. 数据结构( 树形结构,表形数据,对象结构 ) 1 2. 编程语言中对应的数据结构 jav ...

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

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

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

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

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

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

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

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

  6. 使用Oracle数据库实现树形结构表的子-父级递归查询和删除,通过级联菜单简单举例

    前言: 我们在开发中,常常遇到单表的子-父id级联的表结构,在树形的深度不确定的情况下,一次查询出某个树形结构下的所有具有子-父级关系的数据变得十分困难. 这时,我们使用oracle提供的CONNEC ...

  7. 使用Oracle数据库实现树形结构表的子-父级迭代(递归)查询和删除,通过级联菜单简单举例

    前言: 我们在开发中,常常遇到单表的子-父id级联的表结构,在树形的深度不确定的情况下,一次查询出某个树形结构下的所有具有子-父级关系的数据变得十分困难. 这时,我们使用oracle提供的CONNEC ...

  8. 基于ExtJs6前台,SpringMVC-Spring-Mybatis,resteasy,mysql无限极表设计,实现树状展示数据(treepanel)

    先从后台讲起 1.表的设计 parent_id就是另外一条记录的id,无限极表设计可以参考  http://m.blog.csdn.net/Rookie_Or_Veteran/article/deta ...

  9. 「SQL归纳」树形结构表的存储与查询功能的实现——通过路径方法(非递归)

    一.树形结构例子分析: 以360问答页面为例:http://wenda.so.com/c/ 我们通过观察URL,可以明确该页面的数据以树形结构存储,下面三块模块分别为: ①根节点 ②根节点的第一层子节 ...

  10. 树形结构表的存储【转自:http://www.cnblogs.com/huangfox/archive/2012/04/11/2442408.html】

    在数据库中存储树形结构的数据,这是一个非常普遍的需求,典型的比如论坛系统的版块关系.在传统的关系型数据库中,就已经产生了各种解决方案. 此文以存储树形结构数据为需求,分别描述了利用关系型数据库和文档型 ...

随机推荐

  1. cout对象在全局只能拥有一个

    1.问题 在学习符号重载的过程中,有一个想法 std::ostream& operator<<(std::ostream &cout, Person &p); 中s ...

  2. 【面试题精讲】Mysql如何实现乐观锁

    有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 文章更新计划 系列文章地址 在 MySQL 中,可以通过使用乐 ...

  3. [转帖]L4LB for Kubernetes: Theory and Practice with Cilium+BGP+ECMP

    http://arthurchiao.art/blog/k8s-l4lb/ Published at 2020-04-10 | Last Update 2020-08-22 1. Problem De ...

  4. [转帖]认识目标文件的格式——a.out COFF PE ELF

    https://cloud.tencent.com/developer/article/1446849   1.目标文件的常用格式 目标文件是源代码编译后未进行链接的中间文件(Windows的.obj ...

  5. pycharm提交代码到gitee

    1.在pycharm中下载gitee插件,打开pycharm进入settings页面,查看当前页面version control下是否 有gitee,要是没有点击plugins,在搜索框中搜索gite ...

  6. with(上下文管理器)的用法

    with语句可以自动管理上下文资源,不论什么原因(成功或失败)跳出with语句,都能保证文件正确关闭,并 释放资源,不用手动去close掉资源 1.with语句中有两个内置方法__enter__和__ ...

  7. 【代码分享】使用 avx512 + 查表法,优化凯撒加密

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 关于凯撒加密,具体请看:https://en.wikipe ...

  8. 【JS 逆向百例】复杂的登录过程,最新WB逆向

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 逆向目标 本次的逆向目标是 ...

  9. Linux命令-tail命令

    Linux命令-tail 命令分析 命令格式 参数 例子 Linux命令-tail 命令分析 tail命令可用于查看文件的内容,通常用来查看日志,加上-f参数就可以查看最新的日志并且不断刷新. 命令格 ...

  10. SqlSugar基础查询

    查所有 List<Student> list=db.Queryable<Student>().ToList() //select * from Student 查询总数 int ...