Closure Table-树形多级关系数据库设计(MySql)
一般树形多级关系数据库设计,比较普遍的就是四种方法:(具体见 SQL Anti-patterns这本书)
Adjacency List:每一条记录存parent_id
Path Enumerations:每一条记录存整个tree path经过的node枚举(适合深度较浅且固定的业务,字段超长互后将无法命中索引)
Nested Sets:每一条记录存 nleft 和 nright
Closure Table:维护一个表,所有的tree path作为记录进行保存。
本文将以Adjacency List作为原始记录,Closure Table存储上下级关系的方式来解决查询困难问题。
本文限定:删除节点时,仅可删除最末节点,不可从中间删除,否则树不能称之为树。
一:通过parent_id方式保存原始记录
1:如图,现有以下关系

以数据库保存关系如下:

仅以当前表结构,如果仅仅是查询上下级关系,将非常简单,如:
-- 查询西湖区的下级select * from t_area where parent_id = 330106;-- 查询西湖区的上级select * from t_area where id = ( select parent_id from t_arem where id = 330106 )
但是,如果需要查询杭州市的所有下级单位,必须使用递归查询:

如果此时需求是查询"西溪街道"与"杭州市"是否是上下级关系? 那么每次查询都需要递归关系吗?
此时,需要引入Closure Table模式创建上下级关系。
二:创建ClosureTable关系表
结构如下:

数据如下:

此时,如果查询杭州市所有下级单位,SQL如下:

"西溪街道"与"杭州市"是否是上下级关系?

三 :ClosureTable详细使用方法
1:新增数据

如上图,在下城区新增望江街道。
代码如下:
-- 1,新增父子关系
INSERT INTO t_area(id,name,parent_id) VALUES(330102010,'望江街道',330102);-- 2,新增上下级关系
-- 2.1 插入自身
INSERT INTO t_area_closure(ancestor,descendant,level) VALUES(330102010,330102010,0);-- 2.2 为 330102010 的父级 330102 所有上级(包含330102自身)增加下级330102010血缘关系。
INSERT INTO t_area_closure(ancestor,descendant,level)
select ancestor,330102010 as descendant,(level+1) as level from t_area_closure where descendant =330102;
此时,查询330102010的上级关系:(如果不包含自己,则筛选level>0即可)

2:删除数据

如上图,删除杭州市与江干区的关系。
代码如下:
-- 1,删除父子关系(也可以增加逻辑字段进行软删除)
DELETE FROM t_area where id =330104;-- 2,删除关系表。因为是末端删除,只要删除指定数据的父级关系即可DELETE FROM t_area_closure where descendant = 330104;
此时,关系表中已没有330104数据的关系数据

3:变更父子关系

如上图,将西湖区转移到望江街道下面。
简单做法:
删除老的关系。将西湖区、北山街道、西溪街道,按删除数据处理,删除所有关系。
新增关系。在望江街道下面新增西湖区、北山街道、西溪街道关系。
复杂做法:
1,删除老关系。
西湖区、北山街道、西溪街道与杭州市、浙江省的关系将会变更,所以先删除西湖区、北山街道、西溪街道与杭州市、浙江省的上级关系。即,西湖区及下属区域删除西湖区父级以上区域的关系。
-- 1.1 查找指定区域的父级及以上关系
SELECT ancestor from t_area_closure where descendant = 330106 and level >0
-- 1.2 查找区域自己和自己的下级
SELECT descendant from t_area_closure where ancestor = 330106
-- 1.3删除自己和自己的下级 与 自己父级以上区域的关系
delete from t_area_closure where ancestor in ( select ancestor from (SELECT ancestor from t_area_closure where descendant = 330106 and level >0) t1 )
and descendant in ( select descendant from (SELECT descendant from t_area_closure where ancestor = 330106) t2 )
此时删除完成数据后,西湖区自己与下属北山街道、西溪街道的关系依然存在。
2,添加新关系。
2.1 查询新父级的上级关系(包含新父级)

2.2 查找区域自己和自己的下级

2.3 为指定区域自己及下级增加新父级的上级关系。
INSERT INTO t_area_closure(ancestor,descendant,level)
SELECT t1.ancestor,t2.descendant,(t1.level+t2.`level` +1) as level from t_area_closure t1,t_area_closure t2
where t1.descendant =330102010 and t2.ancestor = 330106;
此时,查询北山街道所有上级:

数据正确。
相关文章:
Closure Table-树形多级关系数据库设计(MySql)
一般树形多级关系数据库设计,比较普遍的就是四种方法:(具体见 SQL Anti-patterns这本书) Adjacency List:每一条记录存parent_id Path Enumerations:每一条记录存整个tree path经过的node枚举(…...
【SQL应知应会】表分区(一)• MySQL版
欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle 分区表 • MySQL版 一、分区表1.非分区表2.分区表2…...
java语法基础-- 变量、标识符、关键字
学习目标 教学目标重点难点1.掌握变量的相关概念。2.掌握Java中数据类型的划分。3.掌握8种基本数据类型的使用。4.掌握数据类型的转换方式。5.掌握各个运算符,表达式的作用。6.可以编写简单的Java应用程序。1.对变量的理解。2.基本数据类型的相关信息的记忆。3.数据…...
[STL]stack和queue模拟实现
[STL]stack和queue模拟实现 文章目录 [STL]stack和queue模拟实现stack模拟实现queue模拟实现 stack模拟实现 stack是一种容器适配器,标准容器vector、deque、list都可以作为实现stack的底层数据结构,因为它们都具备以下功能: empty…...
汽车销售企业消费税,增值税高怎么合理解决?
《税筹顾问》专注于园区招商、企业税务筹划,合理合规助力企业节税! 汽车行业一直处于炙手可热的阶段,这是因为个人或者家庭用车的需求在不断攀升,同时随着新能源的技术进一步应用到汽车领域,一度实现了汽车销量的翻倍。…...
flask数据库操作
本文将详细介绍在Flask Web应用中如何设计数据库模型,并使用Flask-SQLAlchemy等扩展进行数据库操作的最佳实践。内容涵盖数据模型设计,ORM使用,关系映射,查询方法,事务处理等方面。通过本文,您可以掌握Flask数据库应用的基本知识。 Flask作为一个流行的Python Web框架,提供了高…...
【C++】 哈希
一、哈希的概念及其性质 1.哈希概念 在顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较。比如顺序表需要从第一个元素依次向后进行查找,顺序查找时间复杂度为…...
TCP三次握手和四次挥手以及11种状态(二)
11种状态 1、一开始,建立连接之前服务器和客户端的状态都为CLOSED; 2、服务器创建socket后开始监听,变为LISTEN状态; 3、客户端请求建立连接,向服务器发送SYN报文,客户端的状态变味SYN_SENT; 4、…...
【华为OD】运维日志排序
题目描述: 运维工程师采集到某产品线网运行一天产生的日志n条,现需根据日志时间先后顺序对日志进行排序,日志时间格式为H:M:S.N。 H表示小时(0~23) M表示分钟(0~59) S表示秒(0~59) N表示毫秒(0~999) 时间可能并没有补全,也就是说&…...
Mag-Fluo-4 AM,镁离子荧光探针,是一种有用的细胞内镁离子指示剂
资料编辑|陕西新研博美生物科技有限公司小编MISSwu PART1----产品描述: 镁离子荧光探针Mag-Fluo-4 AM,具细胞膜渗透性,对镁离子(Mg2) 和钙离子(Ca2)的 Kd 值分别是 4.7mM 和 22mM,…...
与 ChatGPT 进行有效交互的几种策略
在这篇文章中,您将了解即时工程。尤其, 如何在提示中提供对响应影响最大的信息什么是角色、正面和负面提示、零样本提示等如何迭代使用提示来利用 ChatGPT 的对话性质 废话不多说直接开始吧!!! 提示原则 快速工程是有…...
华为云安装MySQL后,本地工具连接MySQL失败
华为云安装MySQL后,本地连接失败 排查问题步骤: 在此之前需要在MySQL创建用户,并赋予权限。 1、能否ping通。 在本地命令行(Windows:winR)通过ping命令,ping服务器地址,看能否ping通。不能则需要检查本地…...
Flink On Yarn模式部署与验证
session运行模式 该模式下分为2步,即使用yarn-session.sh申请资源,然后 flink run提交任务。 1、申请资源yarn-session.sh #在server1执行命令 /usr/local/flink-1.13.5/bin/yarn-session.sh -tm 1024 -n 2 -s 1 -d #申请2个CPU、2g内存 # -tm 表示每个…...
[数据库]对数据库事务进行总结
文章目录 1、什么是事务2、事务的特性(ACID)3、并发事务带来的问题4、四个隔离级别: 1、什么是事务 事务是逻辑上的一组操作,要么都执行,要么都不执行。 事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红…...
【Lua学习笔记】Lua进阶——Table(2)
文章目录 Table的一万种用法二维数组类和结构体Table操作insert & removesortconcat 接上文【Lua学习笔记】Lua进阶——Table,迭代器 Table的一万种用法 二维数组 a {{ 1, 2, 3 },{ 4, 5, 6 }, } print(#a) -->2 for i1,#a dob a[i]for j1,#b doprint(b[…...
如何进行软件回归测试
什么是软件回归测试,如何进行回归测试,进行回归测试时有哪些常用的方法? 回归测试是指修改了旧代码后,重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误的一种测试方法。回归测试是指重复以前的全部或部分的相同功能…...
php://filter绕过死亡exit
文章目录 php://filter绕过死亡exit前言[EIS 2019]EzPOP绕过exit 参考 php://filter绕过死亡exit 前言 最近写了一道反序列化的题,其中有一个需要通过php://filter去绕过死亡exit()的小trick,这里通过一道题目来讲解 [EIS 2019]EzPOP 题目源码&#…...
RS485/RS232自由转ETHERNET/IP网关profinet和ethernet区别
你是否曾经遇到过这样的问题:如何将ETHERNET/IP网络和RS485/RS232总线连接起来呢?捷米的JM-EIP-RS485/232通讯网关,自主研发的ETHERNET/IP从站功能,完美解决了这个难题。这款网关不仅可以将ETHERNET/IP网络和RS485/RS232总线连接起…...
Hadoop_HDFS_常见的文件组织格式与压缩格式
参考资料 1. HDFS中的常用压缩算法及区别_大数据_王知无_InfoQ写作社区 2. orc格式和parquet格式对比-阿里云开发者社区 3.Hadoop 压缩格式 gzip/snappy/lzo/bzip2 比较与总结 | 海牛部落 高品质的 大数据技术社区 4. Hive中的文件存储格式TEXTFILE、SEQUENCEFILE、RCFILE…...
算法与数据结构(四)--排序算法
一.冒泡排序 原理图: 实现代码: /* 冒泡排序或者是沉底排序 *//* int arr[]: 排序目标数组,这里元素类型以整型为例; int len: 元素个数 */ void bubbleSort (elemType arr[], int len) {//为什么外循环小于len-1次?//考虑临界情况…...
别只盯着PID!用STM32的PWM差速控制,让你的循迹小车转弯更稳(附源码分析)
STM32 PWM差速控制:让循迹小车转弯更稳的实战技巧 循迹小车的核心挑战之一是如何实现平滑稳定的转弯控制。许多开发者习惯性地直接套用PID算法,却忽略了更基础的PWM差速控制策略。实际上,通过精心设计的PWM占空比调整方案,完全可以…...
OpenClaw学术研究助手:Qwen3.5-9B-AWQ-4bit解析论文图表数据
OpenClaw学术研究助手:Qwen3.5-9B-AWQ-4bit解析论文图表数据 1. 为什么需要自动化论文图表解析 去年冬天,我在整理一篇关于机器学习模型压缩的综述论文时,遇到了一个典型的研究痛点:需要从32篇相关文献的PDF中提取实验数据表格进…...
XCP或者CCP标定,A2L标定文件,基于map文件自动更新A2L的地址和结构体变量的地址 源...
XCP或者CCP标定,A2L标定文件,基于map文件自动更新A2L的地址和结构体变量的地址 源码基于C#需要开发,编译器为VS2022搞汽车电子的兄弟应该都遇到过这样的问题——辛辛苦苦标定的A2L文件,程序稍微改两行代码,…...
从NTU-RGB+D到实际应用:如何用这个数据集训练一个摔倒检测模型?
基于NTU-RGBD数据集的摔倒检测模型实战指南 在智能监护和安防领域,摔倒检测一直是个极具社会价值的课题。想象一下,当独居老人不慎跌倒时,系统能在第一时间发出警报;或是在建筑工地,实时监测工人安全状态——这些场景背…...
基于合法无代码平台滥用的新型钓鱼攻击机理与防御体系研究
摘要 2026 年 3 月卡巴斯基实验室披露针对 Bubble.io 等正规无代码开发平台的恶意滥用钓鱼攻击,攻击者依托平台高信誉域名、SSL 证书与可视化开发能力,快速生成高仿真钓鱼页面,绕过传统邮件网关与终端检测,实现账号凭证、多因素认…...
机器人双目视觉定位系统设计与开发
机器人双目视觉定位系统设计与开发 摘要 双目视觉定位技术是机器人感知环境、实现自主导航和精准操作的核心技术之一。本系统基于双目立体视觉原理,利用Matlab平台完成了从相机标定、图像采集、立体匹配到三维坐标解算的完整流程。系统采用张正友标定法获取相机内外参数,通…...
实战指南:Autofac 依赖注入在微服务架构中的高效应用
1. Autofac在微服务架构中的核心价值 微服务架构最大的挑战之一就是如何优雅地管理数百个服务的依赖关系。我经历过一个电商系统重构项目,当单体应用拆分成30多个微服务后,手工管理服务依赖就像在玩多米诺骨牌——改一个服务参数可能引发连锁反应。这时候…...
告别“卡脖子”:TVA的0.8秒背后柔性生产与极致效率
作为生产厂长,每天最头疼的不是做出好产品,而是如何在“多品种、小批量、快交期”的频繁切线中,保证产线不停机、不降速。现代汽车零部件企业的生产节奏越来越快,冲压产线往往要求几秒钟甚至零点几秒就出一个件。在这种极限节拍下…...
避坑指南:Doris明细模型(Duplicate Key Model)的5个常见错误及优化方案
避坑指南:Doris明细模型(Duplicate Key Model)的5个常见错误及优化方案 在实时数据分析领域,Apache Doris凭借其卓越的性能和易用性赢得了众多企业的青睐。作为Doris中最基础也最常用的数据模型,明细模型(Duplicate Key Model&…...
3步掌控Windows驱动管理:从冗余清理到系统性能提升全指南
3步掌控Windows驱动管理:从冗余清理到系统性能提升全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer Windows系统随着使用时间增长,驱动存储区会积累大量冗余…...
