很多情况下,一些树状分类关系的都使用递归来查询,用递归来显示,如果数据量大的话,会造成各种麻烦。
我们可以使用树,用先序遍历来代替递归,如表:
create table category ( id varchar(40) primary key, name varchar(100), lft int, rgt int ); insert into category values('1','商品',1,18); insert into category values('2','平板电视',2,7); insert into category values('3','冰箱',8,11); insert into category values('4','笔记本',12,17); insert into category values('5','长虹',3,4); insert into category values('6','索尼',5,6); insert into category values('7','西门子',9,10); insert into category values('8','thinkpad',13,14); insert into category values('9','dell',15,16);
先序遍历的顺序图:
可以发现规律:
- 如果一个节点存在子节点,那么右值与左值之差不为1;其所有子节点的的左右值均小于此节点的左右值。
- 反之则节点为叶节点。
在数据库中的查询语句如下:
select child.name,count(child.name) depth from category parent,category child where child.lft>=parent.lft and child.rgt<=parent.rgt group by child.name order by child.lft; --首先将一个表看成两个表,一张是父节点,一张是子节点 --子节点的左值小于父节点的左值,右值小于父节点的右值,根据这个条件获得存在关系的数据 --对子节点的name进行归组,然后统计个数(count),这样得到有几个上级结点,也就是层次(depth) --最后,按照子节点的左值进行排序
这样,会以很高的效率查询出树状结构,避免了递归的缺点。
在交互层面,列举一个jsp的js示例:
<html> <head> <title>树状结构</title> <!-- 这里使用了xtree --> <script src="${pageContext.request.contextPath }/js/xtree.js"></script> <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/css/xtree.css"> </head> <body> <script type="text/javascript"> <c:forEach var="c" items="${list}"> //这是根结点 <c:if test="${c.depth==1}"> var tree = new WebFXTree('${c.name}'); tree.target="right"; tree.action = "${pageContext.request.contextPath}/servlet/AddChildServlet?id=${c.id}"; </c:if> //这是二级结点 <c:if test="${c.depth==2}"> var node${c.depth} = new WebFXTreeItem('${c.name}'); node${c.depth}.target="right"; node${c.depth}.action = "${pageContext.request.contextPath}/servlet/AddChildServlet?id=${c.id}"; tree.add(node${c.depth}); </c:if> //如果深度大于2级了,直接在node名称上做手脚 <c:if test="${c.depth>2}"> var node${c.depth} = new WebFXTreeItem('${c.name}'); node${c.depth}.target="right"; node${c.depth}.action = "${pageContext.request.contextPath}/servlet/AddChildServlet?id=${c.id}"; node${c.depth-1}.add(node${c.depth}); </c:if> </c:forEach> document.write(tree); </script> </body> </html>