MySQL实现上下级关联的方法简介(MySQL上下关联)

MySQL实现上下级关联的方法简介

在开发一个具有层级关系的系统时,如员工-部门的管理系统、栏目-文章的管理系统等,经常需要使用到上下级关联,也就是父子关系。在MySQL中,实现上下级关联有多种方法,常见的有嵌套集合模型、路径模型和材料化路径模型等。下面我们将对它们进行简单介绍。

1. 嵌套集合模型

嵌套集合模型是一种经典的层次模型,它用一种树结构将数据组织起来,每个节点都包含其子节点的信息,并且可以使用递归查询来实现对整个树形结构的查询。下面是一个示例表:

CREATE TABLE categories (

id INT AUTO_INCREMENT PRIMARY KEY,

name VARCHAR(50) NOT NULL,

parent_id INT,

lft INT NOT NULL,

rgt INT NOT NULL,

depth INT NOT NULL,

UNIQUE KEY(name)

);

其中,lft和rgt两列用于存储节点在树形结构中的左右边界,depth用于表示节点的深度(从0开始)。插入数据时,需要通过递归方式计算出lft、rgt和depth的值:

INSERT INTO categories (name, parent_id, lft, rgt, depth)

VALUES (‘Music’, NULL, 1, 20, 0);

INSERT INTO categories (name, parent_id, lft, rgt, depth)

VALUES (‘Pop’, 1, 2, 7, 1);

INSERT INTO categories (name, parent_id, lft, rgt, depth)

VALUES (‘Rock’, 1, 8, 19, 1);

INSERT INTO categories (name, parent_id, lft, rgt, depth)

VALUES (‘Classic’, 2, 3, 6, 2);

INSERT INTO categories (name, parent_id, lft, rgt, depth)

VALUES (‘Metal’, 3, 4, 5, 3);

INSERT INTO categories (name, parent_id, lft, rgt, depth)

VALUES (‘Indie’, 8, 9, 10, 2);

查询某个节点的子节点可以使用如下查询语句:

SELECT * FROM categories WHERE parent_id = ? ORDER BY lft;

递归查询可以使用MySQL中的WITH RECURSIVE语句:

WITH RECURSIVE cte AS (

SELECT id, name, parent_id, lft, rgt, depth

FROM categories

WHERE id = ?

UNION ALL

SELECT categories.id, categories.name, categories.parent_id, categories.lft, categories.rgt, categories.depth

FROM categories, cte

WHERE categories.parent_id = cte.id

)

SELECT * FROM cte ORDER BY depth;

其中,?表示根节点的id。

使用嵌套集合模型可以方便实现对树形结构的查询,但是在插入、删除和修改节点时需要重新计算整个子树的左右边界,较为复杂。

2. 路径模型

路径模型是一种简单的层次模型,它用一种字符串类型的路径表示父子关系,例如1/2/3表示节点3是节点2的子节点,节点2又是节点1的子节点。下面是一个示例表:

CREATE TABLE categories (

id INT AUTO_INCREMENT PRIMARY KEY,

name VARCHAR(50) NOT NULL,

parent_id INT,

path VARCHAR(255) NOT NULL,

UNIQUE KEY(name)

);

在插入数据时,需要通过递归方式计算出path的值:

INSERT INTO categories (name, parent_id, path)

VALUES (‘Music’, NULL, ‘1/’);

INSERT INTO categories (name, parent_id, path)

VALUES (‘Pop’, 1, ‘1/2/’);

INSERT INTO categories (name, parent_id, path)

VALUES (‘Rock’, 1, ‘1/3/’);

INSERT INTO categories (name, parent_id, path)

VALUES (‘Classic’, 2, ‘1/2/4/’);

INSERT INTO categories (name, parent_id, path)

VALUES (‘Metal’, 4, ‘1/2/4/5/’);

INSERT INTO categories (name, parent_id, path)

VALUES (‘Indie’, 3, ‘1/3/6/’);

查询某个节点的子节点可以使用如下查询语句:

SELECT * FROM categories WHERE parent_id = ?;

递归查询可以使用如下查询语句:

SELECT * FROM categories WHERE path LIKE ‘1/2/%’;

其中,%表示任意长度的后续路径。

路径模型简单易用,但是在查询某个节点的所有祖先节点时需要使用LIKE语句进行模糊查询,效率较低。

3. 材料化路径模型

材料化路径模型是一种在路径模型的基础上进一步优化的方法,它在表中额外保存了节点的所有祖先节点的path信息,以便更加高效地进行查询。下面是一个示例表:

CREATE TABLE categories (

id INT AUTO_INCREMENT PRIMARY KEY,

name VARCHAR(50) NOT NULL,

parent_id INT,

path VARCHAR(255) NOT NULL,

ancestors TEXT,

UNIQUE KEY(name)

);

在插入数据时,需要通过递归方式计算出path和ancestors的值:

INSERT INTO categories (name, parent_id, path, ancestors)

VALUES (‘Music’, NULL, ‘1/’, ”);

INSERT INTO categories (name, parent_id, path, ancestors)

VALUES (‘Pop’, 1, ‘1/2/’, ‘1/’);

INSERT INTO categories (name, parent_id, path, ancestors)

VALUES (‘Rock’, 1, ‘1/3/’, ‘1/’);

INSERT INTO categories (name, parent_id, path, ancestors)

VALUES (‘Classic’, 2, ‘1/2/4/’, ‘1/2/’);

INSERT INTO categories (name, parent_id, path, ancestors)

VALUES (‘Metal’, 4, ‘1/2/4/5/’, ‘1/2/4/’);

INSERT INTO categories (name, parent_id, path, ancestors)

VALUES (‘Indie’, 3, ‘1/3/6/’, ‘1/3/’);

查询某个节点的子节点可以使用如下查询语句:

SELECT * FROM categories WHERE parent_id = ?;

递归查询可以使用如下查询语句:

WITH RECURSIVE cte AS (

SELECT id, name, parent_id, path, ancestors

FROM categories

WHERE id = ?

UNION ALL

SELECT categories.id, categories.name, categories.parent_id, categories.path, categories.ancestors

FROM categories, cte

WHERE categories.id IN (SELECT SUBSTRING_INDEX(ancestors, ‘/’, cte.depth + 1) FROM categories WHERE id = ?)

)

SELECT * FROM cte ORDER BY LENGTH(path);

其中,?表示根节点的id。

使用材料化路径模型可以方便实现对树形结构的查询,并且相较于路径模型,查询某个节点的所有祖先节点的效率更高。但是在插入、删除和修改节点时需要重新计算所有子孙节点的ancestors值,较为复杂。

综上所述,使用嵌套集合模型、路径模型或材料化路径模型都可以实现上下级关联,使用哪种方式取决于具体的应用场景,需要根据系统的需求进行选择。


数据运维技术 » MySQL实现上下级关联的方法简介(MySQL上下关联)