反模式
2019-11-05 本文已影响0人
LJasperliet
树结构
网站的回复评论,这是一种典型的树形结构,拥有层级关系
create table comments{
comment_id,
parent_id,
comment,
forenign key(parent_id) references comments(comment_id)
}
这是一种常见的设计模式,添加parent_id 来表示层级关系。
这种方式很容易查询一个节点的直接后代,但是没有办法查询这个节点下的所有后代。
查询直接后代
select c1.*,c2.* from comments c1 left join comments c2 on c2.parent_id = c1.comments_id;
如果要查询多层节点 需要扩展一个联结
select c1.* ,c2.*,c3.*,c4.*
from comments c1 ---- 第一层
left join comments c2
on c2.parent_id = c1.comment_id ---- 第二层
left join comments c3
on c3.parent_id = c2.comment_id -----第三层
left join comments c4
on c4.parent_id = c3.comment_id; -----第四层
sql查询联结次数是有上限,上面只能查询4层,无法查询跟多,层次太多,执行聚合函数比如count ()也非常困难。
解决方案
1:路径枚举
comment_id,
path,
comment,
}
comment_id | path | comment |
---|---|---|
1 | 1/ | 好 |
2 | 1/2/ | 不错 |
3 | 1/2/3 | 奶茶 |
4 | 1/4 | naice |
如果我们要查询节点7的祖父
select * from comments as c
where '1/4/6/7' like c.path || '%'
|| 是字符串连接符
匹配路径为 1/4/6/% 1/4/% 1/%
将查询路径反过来 获取节点的所有后代
缺点:数据库自身无法保证路径格式总是正确的以及路径中的节点确实存在,需要依赖应用程序逻辑代码维护。长度存在限制。
表设计的时候可以综合考虑使用 邻接表 parent_id和路径 path(1/2/7/)