在本教程中,您将学习如何使用邻接列表模型来管理MySQL中的分层数据。

邻接列表模型介绍

分层数据无处不在。它可以是博客类别(栏目),产品层次结构或组织结构。

有很多方法来管理MySQL中的层次数据,邻接列表模型可能是最简单的解决方案。 由于其简单性,邻接列表模型是开发人员和数据库管理员非常受欢迎的选择。

在邻接列表模型中,每个节点都有一个指向其父节点的指针。顶级节点没有父节点。 请参阅以下类别的电子产品:

在使用邻接列表模型之前,应该熟悉一些术语:

电子设备(Electronics)是顶级节点或根节点。

笔记本电脑,相机和照片,手机和配件(Laptops, Cameras & photo, Phones & Accessories)节点是Electronics节点的子节点。反之亦然Electronics节点是Laptops, Cameras & photo, Phones & Accessories节点的父节点。

叶子节点是没有子节点的节点,例如Laptops,PC,Android,iOS等,而非叶节点是至少有一个子节点的节点。

一个节点的子孙节点被称为后代节点。一个节点的父节点,祖父节点等也被称为祖先节点。

要对此类树进行建模,我们可以创建一个名为category的表,其中包含三个列:id,title和parent_id,如下所示:

CREATE TABLE category (

id int(10) unsigned NOT NULL AUTO_INCREMENT,

title varchar(255) NOT NULL,

parent_id int(10) unsigned DEFAULT NULL,

PRIMARY KEY (id),

FOREIGN KEY (parent_id) REFERENCES category (id)

ON DELETE CASCADE ON UPDATE CASCADE

);

表中的每一行都是由id列标识的树中的一个节点。 parent_id列是category表本身的外键。它像一个指向id列的指针。

插入数据

树的根节点没有父节点,因此parent_id设置为NULL。其他节点必须只有一个父节点。

要插入根节点数据,请将parent_id设置为NULL,如下所示:

INSERT INTO category(title,parent_id)

VALUES('Electronics',NULL);

要插入非根节点,只需要将其parent_id设置为其父节点的ID值。 例如,Laptop & PC和Cameras & Photos,以及Phone & Accessories节点的parent_id设置为1,参考以下语句:

INSERT INTO category(title,parent_id)

VALUES('Laptops & PC',1);

INSERT INTO category(title,parent_id)

VALUES('Laptops',2);

INSERT INTO category(title,parent_id)

VALUES('PC',2);

INSERT INTO category(title,parent_id)

VALUES('Cameras & photo',1);

INSERT INTO category(title,parent_id)

VALUES('Camera',5);

INSERT INTO category(title,parent_id)

VALUES('Phones & Accessories',1);

INSERT INTO category(title,parent_id)

VALUES('Smartphones',7);

INSERT INTO category(title,parent_id)

VALUES('Android',8);

INSERT INTO category(title,parent_id)

VALUES('iOS',8);

INSERT INTO category(title,parent_id)

VALUES('Other Smartphones',8);

INSERT INTO category(title,parent_id)

VALUES('Batteries',7);

INSERT INTO category(title,parent_id)

VALUES('Headsets',7);

INSERT INTO category(title,parent_id)

VALUES('Screen Protectors',7);

查找根节点

根节点是没有父节点的节点。换句话说,它的parent_id为NULL:

SELECT

id, title

FROM

category

WHERE

parent_id IS NULL;

查找节点的直接子节点

以下查询获取根节点的直接子节点,参考以下查询语句 -

SELECT

id, title

FROM

category

WHERE

parent_id = 1;

查找叶节点

叶节点是没有子节点的节点。

SELECT

c1.id, c1.title

FROM

category c1

LEFT JOIN

category c2 ON c2.parent_id = c1.id

WHERE

c2.id IS NULL;

查询整个树

以下递归公用表表达式(CTE)检索整个类别树。 请注意,自从MySQL 8.0起,CTE功能已经可用了。

WITH RECURSIVE category_path (id, title, path) AS

(

SELECT id, title, title as path

FROM category

WHERE parent_id IS NULL

UNION ALL

SELECT c.id, c.title, CONCAT(cp.path, ' > ', c.title)

FROM category_path AS cp JOIN category AS c

ON cp.id = c.parent_id

)

SELECT * FROM category_path

ORDER BY path;

查询子树

以下查询获取ID为7的Phone&Accessories的子树。

WITH RECURSIVE category_path (id, title, path) AS

(

SELECT id, title, title as path

FROM category

WHERE parent_id = 7

UNION ALL

SELECT c.id, c.title, CONCAT(cp.path, ' > ', c.title)

FROM category_path AS cp JOIN category AS c

ON cp.id = c.parent_id

)

SELECT * FROM category_path

ORDER BY path;

得到以下结果 -

查询单个路径

要查询从下到上的单一路径,例如从iOS到Electronics,请使用以下语句:

WITH RECURSIVE category_path (id, title, parent_id) AS

(

SELECT id, title, parent_id

FROM category

WHERE id = 10 -- child node

UNION ALL

SELECT c.id, c.title, c.parent_id

FROM category_path AS cp JOIN category AS c

ON cp.parent_id = c.id

)

SELECT * FROM category_path;

计算每个节点的级别

假设根节点的级别为0,下面的每个节点都有一个等于其父节点的级别加1的级别。

WITH RECURSIVE category_path (id, title, lvl) AS

(

SELECT id, title, 0 lvl

FROM category

WHERE parent_id IS NULL

UNION ALL

SELECT c.id, c.title,cp.lvl + 1

FROM category_path AS cp JOIN category AS c

ON cp.id = c.parent_id

)

SELECT * FROM category_path

ORDER BY lvl;

如下所示 -

删除节点及其后代

要删除节点及其后代,只需删除节点本身,则所有后代将被删除的DELETE CASCADE自动删除

例如,要Laptops & PC节点及其子节点(Laptops , PC),请使用以下语句:

DELETE FROM category

WHERE

id = 2;

删除节点并提升其后子节点

删除非叶节点并提升其后子节点:

首先,将节点的直接子节点的parent_id更新为新父节点的ID。

然后,删除节点。

例如,要删除Smartphones节点并其子项,例如Android,iOS,Other Smartphones节点:

首先,更新Smartphones的所有直接子节点项的parent_id:

UPDATE category

SET

parent_id = 7 -- Phones & Accessories

WHERE

parent_id = 5; -- Smartphones

其次,删除Smartphones节点:

DELETE FROM category

WHERE

id = 8;

两个语句都应该包含在一个事务中:

BEGIN;

UPDATE category

SET

parent_id = 7

WHERE

parent_id = 5;

DELETE FROM category

WHERE

id = 8;

COMMIT;

移动子树

要移动子树,只需更新子树的顶级节点的parent_id。 例如,要移动Cameras & photo作为Phone and Accessories的子节点,可使用以下语句:

UPDATE category

SET

parent_id = 7

WHERE

id = 5;

在本教程中,您已经学会了如何使用邻接列表模型来管理MySQL中的分层数据。

¥ 我要打赏

纠错/补充

收藏

加QQ群啦,易百教程官方技术学习群

注意:建议每个人选自己的技术方向加群,同一个QQ最多限加 3 个群。

mysql+表模型_MySQL邻接列表模型和层次结构相关推荐

  1. 回收mysql表碎片_MySQL表碎片整理

    MySQL表碎片整理 1. 计算碎片大小 要整理碎片,首先要了解碎片的计算方法. 可以通过show table [from|in db_name] status like '%table_name%' ...

  2. mysql 表 类型_mysql表类型

    MySQL支持6种不同的表类型:BDB.InnoDB.HEAP.ISAM.MERGE以及MyISAM.其中 BDB,InnoDB单独属于一类,称为"事务安全型"(transacti ...

  3. mysql 表损坏_MYSQL数据表损坏的原因分析和修复方法小结(推荐)

    1.表损坏的原因分析以下原因是导致mysql 表毁坏的常见原因: 1. 服务器突然断电导致数据文件损坏. 2. 强制关机,没有先关闭mysql 服务. 3. mysqld 进程在写表时被杀掉. 4. ...

  4. mysql 模型_MySQL的架构模型

    看到大牛用户DB架构部的Keithlan<数据库性能优化之查询优化>,在学习过程发现很多不错的东西,就把它保存下来,分享给大家,因为作者说了一句很经典的话:"if you wan ...

  5. mysql 表大小_MySQL查看数据库表容量大小的方法示例

    本文介绍MySQL查看数据库表容量大小的命令语句,提供完整查询语句及实例,方便大家学习使用. 1.查看所有数据库容量大小 select table_schema as '数据库', sum(table ...

  6. mysql表操作_MySQL表操作语句用法百科

    本文采用MySQL5.7.26版本 1 建表语句 建表语句create语法如下: 1.1 设置unsigned unsigned设置数值类型是否为无符号数,可以为空,如下举例: 1.2 设置默认值 d ...

  7. mysql表类型_MySQL表类型的选择

    P131)创建表时的默认引擎是InnoDB,如果要修改默认的存储引擎,可以在参数文件中设置default-table-type.查看当前的默认存储引擎,可以使用一下命令: 创建新表的时候可以通过增加E ...

  8. mysql 表丢失_Mysql数据库备份 部分数据表丢失 Mysql table doesn't exist 解决

    问题: 直接拷贝data下的数据库数据进行备份,重装升级了数据库,直接复制备份数据到新的数据库data目录下,发现部分数据表不见了. 原因分析: 以表"Table"为例: 如类型是 ...

  9. mysql 未知列_mysql – ‘字段列表’连接中的未知列’..’

    您在此查询中至少有两个问题. 首先,当您使用反向标记来分隔标识符时,必须将表别名与列名称分开. `verk.id` -- WRONG `verk`.`id` -- CORRECT 原因是SQL实际上允 ...

最新文章

  1. 刚刚,百度宣布王海峰升任CTO
  2. 为什么要重写 hashcode 和 equals 方法?
  3. 高斯投影正反算C语言程序代码,高斯投影正反算-对网络上面流行的C代码的修改(已正确运行)...
  4. 每天CookBook之JavaScript-059
  5. 943. Find the Shortest Superstring
  6. 信息学奥赛一本通 1061:求整数的和与均值 | OpenJudge NOI 1.5 04
  7. 关于中层管理者的会议态度
  8. 基于JDBC的数据库连接池高效管理策略
  9. 万应低代码CTO胡艳平:浅谈低代码在中大型企业数字化转型中的应用
  10. 2022-2028年中国无线模组行业投资策略探讨及市场规模预测报告
  11. 安装ie9提示未能完成安装_ie11/ie10/ie9安装程序无法验证安装文件
  12. OneApiConnect(一) Fins欧姆龙通讯协议实现源代码
  13. 四月,诗月,你是最美人间四月天。
  14. 微信小程序开发——调用免费天气api接口(高德、天气API)
  15. python的图片转PDF
  16. 深度探索Hyperledger技术与应用之超级账本的典型交易流程
  17. qq申诉网站无法接到服务器,为什么我qq申诉不成功 - 卡饭网
  18. 挽回前男友的方法(挽回必看)
  19. MATLAB 符号表达式与运算全面详细讲解
  20. 罗斯蒙特3051变送器8大方法教你如何选型

热门文章

  1. IDEA快捷键改为eclipse的快捷键(完整版)、常用快捷键、导入已有的设置
  2. numpy.eye()函数简单使用
  3. 11g oracle controlfile 查询,Oracle 11G 隐含参数“_controlfile_autobackup_delay”
  4. Python学习:Windows路径中的转义字符 \ 问题解决办法
  5. 二维码图片文字居中问题
  6. 不可重复读和可重复读的理解
  7. JAVA入门算法题(十五)
  8. 电脑安卓模拟器多开技术模拟器功能使用介绍
  9. 学习Linux命令(33)
  10. 使用iPerf进行网络吞吐量测试