存储在二维表的树结构如何进行指定深度节点的查询
参考实例
例1
Question
在设计ASP.NET网站时,无限分级的商品分类或者论坛板块都可以使用树结构表示,存放到关系型数据库时大家也懂得用Id和ParentId两个字段来表示节点间的关系。
然而这种最省存储空间的表示方法却不是最有效率的,在需要查询指定深度节点时就会遇到问题。我们需要通过递归来逐层展开才能获取到所有该层的节点,然后再在其中进行查询实在既浪费时间又浪费空间。那么有没有更好的做法呢?
Answer
通常在设计表示树结构的数据表时,我们会增加两个字段:
- Depth - 表示当前节点的深度的整数
- Path - 表示从根节点到当前节点的路径的字符串,采用节点名称不可能出现的字符作为分隔符
在对树进行操作时,我们还是如平常一样对表执行CRUD操作,要维护这两个字段并不需要费多少力气,然而在查询时却会为我们带来极大的便利。例如要查询第3层的节点,则只需要使用**“WHERE Depth = 3”;又例如要查询A1节点下B3节点下C2节点下的所有子节点,则可以使用"WHERE Path LIKE ‘A1/B3/C2%’"**。
这样做的道理就在于,通过增加冗余信息来提高检索速度,同时这些冗余信息非常容易维护(个人理解例如 /
, -
等)所以不容易因为操作不慎而导致信息不一致。设想一下你要对树增加/移动/删除一个节点,原本一条SQL语句就能完成的事情现在还是一条SQL语句就能完成,就算不依赖事务也绝对不会导致信息不一致。
明白了这个道理,我们就可以进行推广,例如我们既可能需要根据Id字段的路径来查询,又可能需要根据Name字段的路径来查询,那就分开IdPath
和NamePath
两个字段来表示两组路径字符串。
个人理解:增加维护成本
例2
Question
无限层级表中如何查询上级分类中的所有信息?
正常parent_id,id结构下查询所有上级很复杂(循环查)
Answer
设置parentID
为varchar
类型,将父类id都集中在这个字段里,用符号隔开,比如:1,3,6
这样可以比较容易得到各上级分类的ID,而且在查询分类下的信息的时候,可以使用如:
Select * From information Where cID Like "1,3%"
例3
个人概念绘图
小结
总而言之,增加维护成本来提高查询效率(个人理解不一定对)。
参考博客:
https://www.cnblogs.com/yhb199/archive/2008/07/01/1233153.html