首页 > 数据库, 算法 > 分级查询与递归查询的区别

分级查询与递归查询的区别

概要说明

以oracle数据库hr用户下自带的employees表为例:
要查询出employees表中manager_id为100的雇员的所有下级:

递归查询

在hibernate中可以写如下的hql语句:

"from Employees e where e.manager_id = 100"

递归的方法如下:

public String getEmployeesRoot()
{
	String HQL =“from Employees e where e.manager_id = 100”;
	List list = baseService.getAllByHQL(HQL);
	for(int i=0;i<list.size();i++)
	{
		Employees employees = (Employees) list.get(i);
		Set childNodes = employees.getChilds();
		recursionEmployees (childNodes);
	}
}

private void recursionEmployees(Set childNodes) {
	Iterator it = childNodes.iterator();
	while (it.hasNext()) {
		Employees employees = (Employees) it.next();
		Set node = employees.getChilds();
		if (!node.isEmpty()) {
			recursionEmployees(node);
		}
	}
}

现在对以上的递归查询进行分析:
1、访问数据库的次数:
因为每一个节点在取出来之后都要通过getChild(Set childSet)去取当前节点的子节点,(实际上就是执行from employees e where e.manager_id = ?)并判断是否为空,如果非空则再次进入递归;
所以每一个节点有要请求一次数据库,所有请求次数与树的节点数相同!
2、内存占用程度:
在递归时要存在动态的压栈与弹栈的过程,并随着节点数与节点层数的增加面增加!

分级查询:

写如下sql语句:

Select e.* from
 employees e
start with e.manager_id = 100
connect by prior e.empoyee_id = e.manager_id;

解释:start with (condition)是指以什么样的条件开始。在这儿就可以写是以那个节点 为查询的父节点,
connect by prior (condition) 就是以什么样的条件进行连接。
把子节点条件(employee_id = manager_id)放在前,就是向下遍历树,(不含当前节点)反之(manager_id = employee_id)就是向上遍历树(包含当前节点)。
以上整个sql的意思就是以manager_id为100的节点为起始节点向下遍历树;

public List getAll() {
	String sql = "select e.* from employees e "
			+ "start with e.manager_id = 100"
			+ " connect by prior e.empoyee_id = e.manager_id";
	Query query = getSession().createSQLQuery(sql);
	return query.list();
}

分析以上程序:
1、访问数据库的次数:
只访问一次数据库,访问的次数与树的层数与节点数无关;
2、内存占用:
因为没有频繁的压栈与弹栈操作,所有内存占用少;
3、简单易懂。

关于两种方法的优缺点

递归查询是一个树逐层加载的方式,好处在于能保持树的层次结构,便于形成xml文件;
但是访问数据库次数多,速度慢;
分级查询是一性加载的方式,好处在于可用于数据的计算。但取出数据没有保持树的层次结构。(为了解决此问题,可以在实体设计时加入一个属性来描述树中节点的层次);

除非注明,文章为IT热血青年原创,欢迎转载!转载请注明本文地址,谢谢。
本文地址:http://blog.itblood.com/hierarchical-queries-and-recursive-queries.html

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.