第一种方案:
使用递归算法,也是使用频率最多的,大部分开源程序也是这么处理,不过一般都只用到四级分类。这种算法的数据库结构设计最为简单。category表中一个字段id,一个字段fid(父id)。这样可以根据WHERE id = fid来判断上一级内容,运用递归至最顶层。
分析:通过这种数据库设计出的无限级,可以说读取的时候相当费劲,所以大部分的程序最多3-4级分类,这就足以满足需求,从而一次性读出所有的数据,再对得到数组或者对象进行递归。本身负荷还是没太大问题。但是如果分类到更多级,那是不可取的办法。
这样看来这种分类有个好处,就是增删改的时候轻松了…然而就二级分类而言,采用这种算法就应该算最优先了。
第二种方案:
设置fid字段类型为varchar,将父类id都集中在这个字段里,用符号隔开,比如:1,3,6
这样可以比较容易得到各上级分类的ID,而且在查询分类下的信息的时候,
可以使用:SELECT * FROM category WHERE pid LIKE “1,3%”。
分析:相比于递归算法,在读取数据方面优势非常大,但是若查找该分类的所有 父分类 或者 子分类 查询的效率也不是很高,至少也要二次query,从某种意义看上,个人觉得不太符合数据库范式的设计。倘若递增到无限级,还需考虑字段是否达到要求,而且在修改分类和转移分类的时候操作将非常麻烦。
第三种方案:
使用预排序遍历树算法,也叫左右值算法。特别适用于多层数据结构设计,像Windows,linux下文件夹结构。在这种数据结构中,设置每个节点的左右值为唯一。通过左右值把所有节点连接起来。
数据结构: | |
id: | 类别id,主键 |
name: | 类名 |
lft: | 左值 |
rgt: | 右值 |
分析:这种数据结构的设计完全可以摒弃掉fid,orderview这些字段,按顺序遍历左右值到达查询效果,这种查询速度非常之快,而且只要一次查询就能得到想要的结果,可以轻易的查询节点是否存在子节点,父节点的路径等。但同样面临的在增删改的时候操作比较复杂。这种预排序遍历树算法的核心就是大量牺牲了写的性能来换取读取的性能。而且完全可以扩展到无限级应用。