无限级分类(或菜单)的高性能实现思路
2016-07-25
一般说到无限级分类、菜单之类的东西,大家 (我) 的数据表设计一般是这样的
id | parent_id | title | 更多字段... |
---|---|---|---|
1 | 0 | 衣物 | |
2 | 1 | 上衣 | |
3 | 1 | 裤子 | |
4 | 3 | 西裤 | |
5 | 4 | 长西裤 | |
6 | 4 | 短西裤 | |
7 | 2 | 衬衫 |
其中,parent_id
表示父分类的id。由此可知,衣物分类下有上衣和裤子两个二级分类;而裤子还有西裤这个三级分类……以此类推
这种设计比较常见 (就我所知),但缺点很明显。
例如需要显示下面这样的面包屑导航时:
衣物 > 裤子 > 西裤
就不得不进行多次循环
再例如,需要显示所有分类并表示层级时:
也不得不进行多次循环
那么,如何快速实现上述的常见功能呢?
实现
首先,示例表设计:
id | title | path | level | 更多字段... |
---|---|---|---|---|
1 | 衣物 | 0 | 0 | |
2 | 上衣 | 0,1 | 1 | |
3 | 裤子 | 0,1 | 1 | |
4 | 西裤 | 0,1,3 | 2 | |
5 | 长西裤 | 0,1,3,4 | 3 | |
6 | 短西裤 | 0,1,3,4 | 3 | |
7 | 衬衫 | 0,1,2 | 2 |
其中,path
表示父级id列表。例如西裤的0,1,3
就表示衣物 > 裤子
实现面包屑时只要取出path
字段的值,然后用,
分割,得到id列表
再用where id in (1,3)
即可
需要显示所有分类并表示层级时,使用下面的SQL:
SELECT *,concat(path,',',id) AS paths FROM menu ORDER BY paths
看到的结果是这样的:
id | title | path | level | paths |
---|---|---|---|---|
1 | 衣物 | 0 | 0 | 0,1 |
2 | 上衣 | 0,1 | 1 | 0,1,2 |
7 | 衬衫 | 0,1,2 | 2 | 0,1,2,7 |
3 | 裤子 | 0,1 | 1 | 0,1,3 |
4 | 西裤 | 0,1,3 | 2 | 0,1,3,4 |
5 | 长西裤 | 0,1,3,4 | 3 | 0,1,3,4,5 |
6 | 短西裤 | 0,1,3,4 | 3 | 0,1,3,4,6 |
那么,直接取出结果输出即可。level
字段就是层级的意思
例如在PHP中,可以用str_repeat('--> ', $level)
直接输出表示层级的前缀
并且连顺序都排好了,是不是很方便呢?
怎么让他们变成多维数据的形式
ac58cc3f3866e1620bfaa470c20f8088啊
有没有实际例子可以观摩?
sql 语句都给出了还要啥例子?
请问这种结构要想实现一个父级分类迁移到另一个子级分类下,如何优化效率?
以文中表格为例,假设要将西裤(ID:4)移动到衬衫(ID:7)下。首先 西裤level=衬衫level+1,用sql replace语句将path字段内的“0,1,3”替换为衬衫path+",7"(即0,1,2,7)即可
怎么排序呢,比如裤子要放在上衣前面的时候
加权重字段,SQL语句order加多个条件
0,1,2和0,1,3后面加没有用的呀,
这个方法真好用,赞一个,我之前还用递归的方法挨个比对
虽然我都知道,但是也要点个赞啊
可以可以,6!