当前位置: 首页 > 编程日记 > 正文

树形结构在关系数据库中的设计

在程序设计中,经常以树形结构表示数据的层次关系,如菜单的结构、商品的分类等。

这样的层次结构在关系数据库中难以直观地表示。常见的一种做法是用一个字段指向上级节点来表示记录的上下级关系。

fidpidfname
1Food
21Fruit
32Red
43Cherry
52Yellow
65Banana
71Meat
87Beef
97Pork

当要查询某一节点的上一级节点,比如 Beff,可以查询 Beff(pid=7) 指向的那条记录。

SELECT * FROM food WHERE fid = 7;

当要查询某一节点的下一级节点,比如 Fruit,可以查询 pid 指向 Fruit(fid=2) 的记录。

SELECT * FROM food WHERE pid = 2;

另有一种基于左右值编码的设计,这种设计方式的表结构如下:

fidfnamelftrgt
1Food118
2Fruit211
3Red36
4Cherry45
5Yellow710
6Banana89
7Meat1217
8Beef1314
9Pork1516

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" 标识。

fidfname
aFood
aaFruit
aaaRed
aaaaCherry
aabYellow
aabaBanana
abMeat
abaBeef
abbPork

当要查询某一节点的上一级节点,比如 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

相关文章:

Java项目:在线课程会员系统(java+Springboot+Maven+JSP+Spring+Mysql+layui)

一、项目简述 功能包括: 用户管理,课程管理,在线视频观看,评论,会员展示,会员充值等等。 二、项目运行 环境配置: Jdk1.8 Tomcat8.5 mysql Eclispe(IntelliJ IDEA,Eclispe,MyEc…

职场观察:高薪需要什么?

标签:职场高薪原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://xjsunjie.blog.51cto.com/999372/1378547新的一年,看到别人跳槽或涨薪,你是否也蠢蠢欲动…

Excel-姓名列中同一个人汇总金额列,得出总金额

8、姓名列中同一个人求和金额列,得出总金额。 方法一: P2处公式SUMPRODUCT(($M$2:$M$20$M2)*($N$2:$N$20)) 解释函数: 引用:https://zhinan.sogou.com/guide/detail/?id1610011625 PS:这个只是单条件求和,…

C语言编译全过程(转贴)

C语言编译全过程 编译的概念:编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件…

Java项目:家教管理系统(java+SSM+MyBatis+MySQL+Maven+Jsp)

源码获取:博客首页 "资源" 里下载! 该系统分为前台和后台 前台功能有:登录、注册、查看学员、查看教师、个人中心等。 后台功能有:用户管理、学员管理、教师管理、审核管理、公告管理、新闻管理、简历管理等。前台注册…

ecshop /api/client/api.php、/api/client/includes/lib_api.php SQL Injection Vul

catalog 1. 漏洞描述 2. 漏洞触发条件 3. 漏洞影响范围 4. 漏洞代码分析 5. 防御方法 6. 攻防思考 1. 漏洞描述 ECShop存在一个盲注漏洞,问题存在于/api/client/api.php文件中,提交特制的恶意POST请求可进行SQL注入攻击,可获得敏感信息或操作…

C++ 检测内存泄露

本文描述了如何检测内存泄露。最主要的是纯C,C的程序如何检测内存泄露。 现在有很多专业的检测工具,比如比较有名的BoundsCheck, 但是这类工具也有他的缺点,我认为首先BoundsCheck是商业软件,呵呵。然后呢需要安装,使用…

Java 学习笔记(4)——java 常见类

上次提前说了java中的面向对象,主要是为了使用这些常见类做打算,毕竟Java中一切都是对象,要使用一些系统提供的功能必须得通过类对象调用方法。其实Java相比于C来说强大的另一个原因是Java中提供了大量可用的标准库 字符串 字符串可以说是任何…

浅谈GCC预编译头技术

浅谈GCC预编译头技术 文/jorge ——谨以此文,悼念我等待MinGW编译时逝去的那些时间。 其 实刚开始编程的时候,我是丝毫不重视编译速度之类的问题的,原因很简单,因为那时我用BASICA。后来一直用到C Builder,尽管Borl…

Java项目:慢病报销管理信息系统(java+MySQL+Jdbc+Servlet+Jsp)

源码获取:博客首页 "资源" 里下载! 一、项目简述 功能: 慢病管理,医疗机构管理,家庭管理,费用交纳,费用报销,报表统计等等功能。 二、项目运行 环境配置: Jd…

Jetty Cross Origin Filter解决jQuery Ajax跨域访问的方法

当使用jQuery Ajax post请求时可能会遇到类似这样的错误提示 XMLHttpRequest cannot load http://xxxxxx. Origin http://xxxxxx is not allowed by Access-Control-Allow-Origin. 这是Ajax跨域访问权限的问题,服务器端不接受来自另一个不同IP地址的由脚本文件发出的…

php 遍历所有的文件

<?php prin_r(glob($path)); 2 转载于:https://www.cnblogs.com/zqk8553/p/3640071.html

Oracle数据库物理存储结构管理

1、实验目的 &#xff08;1&#xff09;掌握Oracle数据库数据文件的管理。 &#xff08;2&#xff09;掌握Oracle数据库控制文件的管理。 &#xff08;3&#xff09;掌握Oracle数据库重做日志文件的管理。 &#xff08;4&#xff09;掌握Oracle数据库归档管理。 2、实验环境 Wi…

KDE与GNOME的战争史(转载)

虽然在商业方面存在竞争&#xff0c;GNOME与KDE两大阵营的开发者关系并没有变得更糟&#xff0c;相反他们都意识到支持对方的重要性—如果KDE和GNOME无法实现应用程序的共享&#xff0c;那不仅是巨大的资源浪费&#xff0c;而且将导致Linux出现根本上的分裂。 KDE与GNOME是…

[ActionScript 3.0] AS向php发送二进制数据方法之——在URLRequest中构造HTTP协议发送数据...

主类 HTTPSendPHP.as 1 package 2 {3 import com.JPEGEncoder.JPGEncoder;4 import com.fylib.httpRequest.HttpRequestBuilder;5 import com.fylib.httpRequest.HttpRequestBuilderConsts;6 import flash.display.Bitmap;7 import flash.display.BitmapDa…

Java项目:校园招聘平台系统(java+MySQL+Jdbc+Servlet+SpringMvc+Jsp)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 一、项目简述 功能&#xff1a; 用户和企业用户的注册登录&#xff0c;简历的筛选查看搜索&#xff0c;应聘信息互动等等。 二、项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 mysql Eclispe&#xf…

静态资源(StaticResource)和动态资源(DynamicResource)

静态资源&#xff08;StaticResource&#xff09;和动态资源&#xff08;DynamicResource&#xff09; 资源可以作为静态资源或动态资源进行引用。这是通过使用 StaticResource 标记扩展或 DynamicResource 标记扩展完成的。 StaticResource 通过替换已定义资源的值来为 XAML 属…

如何在 Kaggle 首战中进入前 10%(转)

如何在 Kaggle 首战中进入前 10%&#xff08;转&#xff09; 来源&#xff1a;https://dnc1994.com/2016/04/rank-10-percent-in-first-kaggle-competition/ Introduction 本文采用署名 - 非商业性使用 - 禁止演绎 3.0 中国大陆许可协议进行许可。著作权由章凌豪所有。 Kaggle …

一.Timesten安装

一&#xff0c;安装timesten IMDB并测试 1. 创建数据库相关用户和组 groupadd timestenuseradd -g timesten -G dba timestenpasswd timesten2. 创建相关目录 mkdir /etc/TimesTenchmod 775 /etc/TimesTenchown timesten:timesten /etc/TimesTenmkdir /u01/app/timesTen chmod …

linux 入门-1

刚开始接触linux&#xff0c;总有些简单的问题不知道怎么搞定&#xff0c;先将目前汇总的解决方法叫做"linux入门&#xff0d;1",后续在使用过程中逐步总结。 1. 连接 ADSL &#xff1a; sudo pon dsl-provider 断开 ADSL&#xff1a; sudo poff 查看 ADSL 状态&a…

Java项目:家庭理财系统(java+SSM+JSP+Tomcat8+Mysql)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 一、项目简述 功能&#xff1a;家庭理财&#xff0c;财务分析&#xff0c;统计等等。 二、项目运行 运行环境: jdk8tomcat8mysqlIntelliJ IDEA&#xff08; Eclispe , MyEclispe ,Sts 都支持&#xff0c;代…

ORA-19809: 超出了恢复文件数的限制

实验环境&#xff1a;Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod 实验背景&#xff1a;向tough.t中插入40万条记录&#xff0c;然后rollback&#xff0c;接着执行了shutdown abort命令。当重新启动数据库的时候遇到以下问题。 SQL> alter database …

VC manifest

manifest原理和用途 dll是被动态调用的&#xff0c;所以会被若干个程序共享使用的 但是如果dll在应用程序不知道的情况下升级了、或是被另一个程序更改了&#xff0c;就可能会出现问题&#xff0c;即”DLL Hell” 随着系统资源越来越丰富&#xff0c;硬盘不那么紧张&#xff0…

判断年月日是否正确

//输入年月日 Console.Write("请输入年&#xff1a;"); int year Convert.ToInt32(Console.ReadLine()); Console.Write("请输入月&#xff1a;"); int month Convert.ToInt32(Console.ReadLine()); Console.Write("请输入日&#xff1a;"); i…

Java项目:农业计算工具(java+swing)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 1、换算:吨、千克、斤&#xff0c;晌/公顷、亩、平方米&#xff0c;晌/株、亩/株、平方米/株 2、籽粒干重、果穗干重、出籽率计算 3、发芽种粒数、供试种粒数、发芽率计算 4、种子袋、晌、亩、品种 换算 pac…

web网站加速之CDN(Content Delivery Network)技术原理

2019独角兽企业重金招聘Python工程师标准>>> 在不同地域的用户访问网站的响应速度存在差异,为了提高用户访问的响应速度、优化现有Internet中信息的流动,需要在用户和服务器间加入中间层CDN. 使用户能以最快的速度&#xff0c;从最接近用户的地方获得所需的信息&…

response.getWriter().write()和 response.getWriter().print()的区别

异步上传图片的代码。发现里面用了response.getWriter().print(),故联想到response.getWriter().writer&#xff08;&#xff09;,经过一番api的查找与实操&#xff0c;总结如下&#xff1a; response.getWriter()返回的是PrintWriter&#xff0c;这是一个打印输出流。response…

c语言中volatile关键字的作用

读文章之前 可以先看一下《程序员的自我修养 》第28页 过度优化。 volatile 提醒编译器它后面所定义的变量随时都有可能改变&#xff0c;因此编译后的程序每次需要存储或读取这个变量的时候&#xff0c;都会直接从变量地址中读取数据。如果没有 volatile关键字&#xff0c;则编…

Java项目:抽奖点名神器(HTML+可自定义抽选)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 用于年终抽奖或随机点名神器 //获取页面元素var student_box document.getElementById("student_box");//循环生成HTMLvar html "";for (var i 0 ; i < 22; i ) {html <div st…

Hive Metastore 连接报错

背景 项目中需要通过一些自定义的组件来操控hive的元数据&#xff0c;于是使用了remote方式来存储hive元数据&#xff0c;使用一个服务后台作为gateway&#xff0c;由它来控制hive元数据。 现象 在windows上连接hive metastore的时候&#xff0c;无端的会报NullPointerExceptio…