数据库构建树状分类结构

邻接表

https://my.oschina.net/XYleung/blog/99604

缺点:
这种方法很简单,容易理解,好上手。但是也有一些缺点。主要是因为运行速度很慢,由于得到每个节点都需要进行数据库查询,数据量大的时候要进行很多查询才能完成一个树。另外由于要进行递归运算,递归的每一级都需要占用一些内存所以在空间利用上效率也比较低。

预排序遍历树算法

左右值无限分类

表结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE TABLE `user_cgroup` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分组id',
`pid` bigint(20) NOT NULL DEFAULT '0' COMMENT '父id',
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '组名称',
`user_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '企业用户ID',
`is_default` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否默认分组',
`node_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '节点类型0-普通节点;1-头结点',
`lft` bigint(20) NOT NULL DEFAULT '0' COMMENT '左值',
`rgt` bigint(20) NOT NULL DEFAULT '0' COMMENT '右值',
`create_time` bigint(20) NOT NULL DEFAULT '0',
`seqno` bigint(20) NOT NULL DEFAULT '0' COMMENT '序号',
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=974 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='企业分组';

添加头结点

1
INSERT INTO user_cgroup(name,user_id,node_type,lft,rgt)VALUES('name',1,1,1,2)

插入节点

p:父节点

1
2
3
UPDATE user_cgroup SET rgt=rgt+2 WHERE user_id=1 AND rgt>p.lft
UPDATE user_cgroup SET lft=lft+2 WHERE user_id=1 AND lft>p.lft
INSERT INTO user_cgroup(pid,name,user_id,lft,rgt)VALUES(1,"child",1,p.lft+1,p.lft+2)

删除节点

i:当前节点

1
2
3
DELETE FROM user_cgroup WHERE user_id=1  AND  lft BETWEEN i.lft AND i.rgt
UPDATE user_cgroup SET lft=lft-(i.rgt-i.lft + 1) WHERE user_id=1 AND lft>i.rgt
UPDATE user_cgroup SET rgt=rgt-(i.rgt-i.lft + 1) WHERE user_id=1 AND rgt>i.rgt

查询节点下所有成员

i:当前节点

1
SELECT id FROM user_cgroup WHERE user_id=1 AND lft>i.lft AND rgt<i.rgt

查询节点下所有成员的叶子节点

i:当前节点

1
SELECT id FROM user_cgroup WHERE user_id=1 AND lft>=i.lft AND rgt<=i.rgt AND lft+1=rgt

查询节点下的儿子节点

i:当前节点

1
2
3
4
5
6
7
8
9
10
11
12
13
select id from (
select
node.*, count(parent.id) as deep
from
user_cgroup as node,
user_cgroup as parent
where node.lft between parent.lft and parent.rgt
and node.user_id=1 and parent.user_id=1
and (node.lft>i.lft and node.rgt<i.rgt)
and (parent.lft>i.lft and parent.rgt<i.rgt)
group by node.id
order by node.lft
) as a where a.deep <= 1 order by a.seqno,a.lft

总结:

查询多使用预排序遍历树算法
修改多使用邻接表