树形结构在关系数据库中的设计
在程序设计中,经常以树形结构表示数据的层次关系,如菜单的结构、商品的分类等。
这样的层次结构在关系数据库中难以直观地表示。常见的一种做法是用一个字段指向上级节点来表示记录的上下级关系。
fid | pid | fname |
1 | Food | |
2 | 1 | Fruit |
3 | 2 | Red |
4 | 3 | Cherry |
5 | 2 | Yellow |
6 | 5 | Banana |
7 | 1 | Meat |
8 | 7 | Beef |
9 | 7 | Pork |
当要查询某一节点的上一级节点,比如 Beff,可以查询 Beff(pid=7) 指向的那条记录。
SELECT * FROM food WHERE fid = 7;
当要查询某一节点的下一级节点,比如 Fruit,可以查询 pid 指向 Fruit(fid=2) 的记录。
SELECT * FROM food WHERE pid = 2;
另有一种基于左右值编码的设计,这种设计方式的表结构如下:
fid | fname | lft | rgt |
1 | Food | 1 | 18 |
2 | Fruit | 2 | 11 |
3 | Red | 3 | 6 |
4 | Cherry | 4 | 5 |
5 | Yellow | 7 | 10 |
6 | Banana | 8 | 9 |
7 | Meat | 12 | 17 |
8 | Beef | 13 | 14 |
9 | Pork | 15 | 16 |
fid 跟节点的层次完全没有关系,仅仅用来标识节点。引入了左右值来表示节点之间的关系,如下图所示。
这样的设计能够方便地遍历一棵树,从左值数到右值便是先序遍历了一棵(子)树。更多详细的设计,参见 http://www.sitepoint.com/hierarchical-data-database/ 和 http://blog.csdn.net/monkey_d_meng/article/details/6647488
最后一种自己想到的设计:用字符串 str 来标识节点,并约定标识其上级节点的字符串为 substr(str, 1, length(str)-1)。例如,有一节点的以 "abc" 标识,则其上级节点以 "ab" 标识。
fid | fname |
a | Food |
aa | Fruit |
aaa | Red |
aaaa | Cherry |
aab | Yellow |
aaba | Banana |
ab | Meat |
aba | Beef |
abb | Pork |
当要查询某一节点的上一级节点,比如 Beff,因为 Beff 的 fid 为 "aba", 所以其上级节点的 fid 为 "ab"。
SELECT * FROM food WHERE fid = 'ab';
当要查询某一节点的路径,比如 Beff,因为 Beff 的 fid 为 "aba",所有其路径为 a/ab/aba。
SELECT * FROM food WHERE fid IN ('a', 'ab', 'aba') ORDER BY fid;
当要查询某一节点的下一级节点,比如 Fruit,因为 Fruit 的 fid 为 "aa",所以其下一级节点的 fid 是以 "aa" 开头且比 "aa" 多一个字符的字符串。
SELECT * FROM food WHERE fid LIKE 'aa_';
当要查询某一节点的所有下级节点,比如 Fruit,因为 Fruit 的 fid 为 "aa",所以其所有下级节点的 fid 是以 "aa" 开头的字符串。
SELECT * FROM food WHERE fid LIKE 'aa%' AND fid != 'aa';
总结
第一种设计方式, 直观方便,但是在对树的遍历过程中需要递归查询,数据量大时,对效率的影响很大。这种设计适合的场景:1) 数据量不大的时候; 2) 只会经常查询节点的下一级节点而不会频繁查询节点的所有下级节点。
基于左右值编码的设计方式,消除了遍历树时的递归操作,查询效率高,但是设计较为复杂,增删节点的代价较大。
第三种设计方式,同样删除了遍历树是的递归操作,无论是广度优先搜索(ORDER BY LENGTH(fid))还是深度优先搜索(ORDER BY fid),都极为方便。这种设计在增删节点时会影响着节点的所有下级节点的标识编码。这种设计方式适合的场景:1) 树形结构基本稳定,很少需要对其增删节点; 2) 需要频繁地查询某个节点的所有下级节点。
转载于:https://www.cnblogs.com/huey/p/4518979.html
树形结构在关系数据库中的设计相关推荐
- 树形结构与关系数据库之闭包表
闭包表记录了树中所有节点的关系,不仅仅只是直接父子关系,它需要使用2张表,除了节点表本身之外,还需要使用1张表来存储节祖先点和后代节点之间的关系(同时增加一行节点指向自身),并且根据需要,可以增加一个 ...
- android treeview 树形结构,前端开发中,使用TreeView控件创建树形结构
原标题:前端开发中,使用TreeView控件创建树形结构 Wijmo是一款使用Type编写的新一代Java/HTML5控件集.它秉承触控优先的设计理念,在全球率先支持AngularJS,并提供性能卓越 ...
- 数据库树形结构、多级联动的表设计
问题:二级联动.多级联动等树形结构的数据,如何设计表格. 场景:省市县三级联动.商品的分类等. 参考:https://www.zhihu.com/question/20417447 最常用的一种方法是 ...
- 把数据转换为在内存中Tree(树形结构)。_备战秋招:一文搞定数据库常见面试题...
点击上方"蓝字",关注了解更多 1.数据库范式 第一范式:列不可分,eg:[联系人](姓名,性别,电话),一个联系人有家庭电话和公司电话,那么这种表结构设计就没有达到 1NF: 第 ...
- MySQL:如何将树形结构存储在数据库中
文章目录 问题 方案一 Adjacency List(存储父节点) 数据库存储结构 SQL示例 1.添加节点 2.查询小天的直接上司 3.查询老宋管理下的直属员工 4.查询小天的所有上司 5.查询老王 ...
- NET平台下Web树形结构程序设计
.NET平台下Web树形结构程序设计 李洪根 我的上篇文章<树形结构在开发中的应用>主要是在Windows Form下的实现,下面讲一下Web Form下的实现. 概述 TreeView是 ...
- .NET平台下Web树形结构程序设计
.NET平台下Web树形结构程序设计 我的上篇文章<树形结构在开发中的应用>主要是在Windows Form下的实现,下面是Web Form下的实现. 数据库设计 首先,我们在SQL SE ...
- 组合模式 -- 树形结构处理
树形结构在软件中随处可见,例如操作系统中的目录结构.应用软件中的菜单.办公系统中的公司组织结构等等,如何运用面向对象的方式来处理这种树形结构是组合模式需要解决的问题,组合模式通过一种巧妙的设计方案使得 ...
- java8 获取部门树形结构
需求:从mysql数据库中查出所有的部门组织,按照父子关系,组成树形结构返回给前端 数据库设计: DROP TABLE IF EXISTS `management_info`; CREATE TABL ...
最新文章
- 如何在Ruby中写入文件?
- mysql bit 和 tinyint 的区别及使用场景?
- Faster-RCNN算法精读
- 举例讲清楚模型树和回归树的区别
- 关于SQL Server 存储过程的EXECUTE AS CALLER选项
- LeetCode 1059. All Paths from Source Lead to Destination
- ClickHouse常用sql语句
- SD与SE的关系,以及异常值
- 安装Hadoop2.10.1
- java正则表达式逗号_java – 接受逗号或分号分隔值的正则表达式模式
- 基于人脸识别的门禁系统设计PPT汇报
- Ceres的Options详解
- java修改文件只读_java修改文件为只读权限
- WLC RTU license
- can not be named yunan because its located directly under the workspace root
- Monte Carlo Integration 蒙特卡罗方法求积分 附简单例题+代码
- Python报错:ImportError cannot import name ‘imresize‘
- 实战SV验证学习(lab4)
- 2014美图网校园招聘Android实习工程师笔试试卷详解
- 【现代操作系统】第一章:引论