SQL反模式-简单树问题(二)

      上一篇文章介绍,简单树的结构不能使用上级Id来存储,会带来查询等问题,并提供了2个解决方案。分别是使用存储全路径的列和嵌套集合(nested sets)

解决方案:闭包表(Closure Table)

      这种方案是简单且优雅的,那么具体方案是什么呢?它需要额外建一个表,比如TreePaths表,这个表的结构是这样的

Employee

------------------

emp_id

emp_name

TreePaths

-------------

ancestor(祖先),关联emp_id

descendant(后代),关联emp_id

这两列的结构与emp_id一致,并且是emp_id的外键,假设employee表的各个节点层级如下,上面表示管理者

其中A(id为1)是B、C的管理者,C管理D、E

那么这个层级关系如何存储到TreePaths中呢?

ancestordescendant
11
12
13
14
15
22
33
34
35
44
55

 

以上数据表格存储了所有节点的层级关系,有了以上关系之后,那么想找到id为3的下属有哪些,可以使用如下SQL

select e.* from Employee e 
inner join TreePaths t on e.emp_id =t.descendant
where t.ancestor =3;

如果查询id为5的上级有哪些,可以使用如下SQL

select e.* from Employee e 
inner join TreePaths t on e.emp_id =t.ancestor
where t.descendant =5;

假设需要删除id为3的节点和子树,则使用如下SQL就可以了。当然可以仅删除TreePaths,而不是删除Employee。

delete Employee where emp_id 
in (SELECT descendant from TreePaths where ancestor =3);

delete TreePaths where descendant in
(SELECT descendant from TreePaths where ancestor =3);

上面的TreePaths可以增加一些列用于跟好的查询,比如增加path_length,这样可以去到不同层级的管理者或者下属信息,有兴趣可以自己研究一下。

最后附上SQL,供大家使用

create table Employee
(emp_id int,
emp_name nvarchar(50));
insert into Employee values
(1,'A'),
(2,'B'),
(3,'C'),
(4,'D'),
(5,'E');

CREATE TABLE TreePaths
(ancestor int,
descendant int);

insert into TreePaths values
(1,1),
(1,2),
(1,3),
(1,4),
(1,5),
(2,2),
(3,3),
(3,4),
(3,5),
(4,4),
(5,5)

select * from TreePaths;

select e.* from Employee e 
inner join TreePaths t on e.emp_id =t.descendant
where t.ancestor =3;

select e.* from Employee e 
inner join TreePaths t on e.emp_id =t.ancestor
where t.descendant =5;

delete Employee where emp_id 
in (SELECT descendant from TreePaths where ancestor =3);

delete TreePaths where descendant in
(SELECT descendant from TreePaths where ancestor =3);

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值