我在mysql中有一个巨大的员工数据,它有一个属性作为父id,它存储每个员工的主管,并以层次结构定义。每个用户都在其他员工的领导下工作,并处理4-5名成员的团队。我经常需要主管或下属树,我使用递归函数来获取其团队的雇员。请给我推荐一种方法,这样我就不必每次需要员工数据时都调用递归函数。使用“视图或存储过程”是个好主意吗?
谢谢。
发布于 2011-01-09 19:14:59
当您使用存储过程时,仍然需要递归。您只需将递归从PHP源代码移动到数据库。
您可以使用nested sets来存储分层数据。这消除了递归,代价是插入、删除和重定位的成本更高。基本上,您创建了两个额外的字段left
和right
,其中left < right
和e1
是e2
的下级of e1.left > e2.left && e1.right < e2.right
。
这使得SELECT查询很难读懂,但却很有效。在所有其他方法都失败的情况下执行此操作。
发布于 2011-01-09 19:32:52
下面是一个非递归存储过程实现,它显然只需要从应用程序代码中调用一次,而不需要n次调用(树的每一层都需要一个)。我建议远离嵌套的集合,坚持你的邻接表实现-想想 Oracle的连接和sql server中的CTE -不用再多说了。
drop table if exists employees;
create table employees
(
emp_id smallint unsigned not null auto_increment primary key,
name varchar(255) not null,
boss_id smallint unsigned null,
key (boss_id)
)
engine = innodb;
insert into employees (name, boss_id) values
('f00',null),
('ali later',1),
('megan fox',1),
('jessica alba',3),
('eva longoria',3),
('keira knightley',5),
('liv tyler',6),
('sophie marceau',6);
drop procedure if exists employees_hier;
delimiter #
create procedure employees_hier
(
in p_emp_id smallint unsigned
)
begin
declare v_done tinyint unsigned default(0);
declare v_dpth smallint unsigned default(0);
create temporary table hier(
boss_id smallint unsigned,
emp_id smallint unsigned,
depth smallint unsigned
)engine = memory;
insert into hier select boss_id, emp_id, v_dpth from employees where emp_id = p_emp_id;
/* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */
create temporary table emps engine=memory select * from hier;
while not v_done do
if exists( select 1 from employees e inner join hier on e.boss_id = hier.emp_id and hier.depth = v_dpth) then
insert into hier select e.boss_id, e.emp_id, v_dpth + 1
from employees e inner join emps on e.boss_id = emps.emp_id and emps.depth = v_dpth;
set v_dpth = v_dpth + 1;
truncate table emps;
insert into emps select * from hier where depth = v_dpth;
else
set v_done = 1;
end if;
end while;
select
e.emp_id,
e.name as emp_name,
p.emp_id as boss_emp_id,
p.name as boss_name,
hier.depth
from
hier
inner join employees e on hier.emp_id = e.emp_id
left outer join employees p on hier.boss_id = p.emp_id;
drop temporary table if exists hier;
drop temporary table if exists emps;
end #
delimiter ;
-- call this sproc from your php
call employees_hier(1);
发布于 2011-01-09 21:38:12
看看这些链接:
https://stackoverflow.com/questions/4638728
复制相似问题