我遇到了一个严重的问题。
我正在一个数据库中工作,其中一个用户是先前注册用户的孩子。
那个孩子将有另外两个孩子用户。
这是n级
所以我试图找出问题出现的第n级用户的最多父母
现在我使用循环中运行的查询来查找这个,但我知道它很奇怪,一旦级别开始增加,我的数据库服务器就会挂起。
有人请告诉我一些事情。可以使用存储过程吗?
答案 0 :(得分:0)
你可以在这里找到答案:http://sqlpro.developpez.com/cours/arborescence/(查看英文文件)。
这意味着您必须再次设计表格,但有些搜索查询会更快(避免递归)。
答案 1 :(得分:0)
您需要从一个查询中的数据库 中获取每个用户的第一级
将所有结果变为大数组,
在您的服务器端语言中,您可以运行找到最多父级的算法
不要使用sql查询来执行此操作。
答案 2 :(得分:0)
MySQL没有分层查询,因此无法通过SQL有效地完成此操作。您必须在写入期间计算此查询的数据,而不是在读取期间。
只需在表格中添加“最父母”列。或者您可以添加一个sting值,您可以在其中存储当前记录的路径。例如
id parent path
1 null null
2 1 /1/
3 2 /1/2/
....
答案 3 :(得分:0)
这是一个简单的示例,需要单个非递归数据库调用来生成员工层次结构。您应该可以轻松地将其与您的模型相适应。
可在此处找到完整脚本:http://pastie.org/1266734
希望有所帮助:)
MySQL调用示例
call employees_hier(1);
call employees_hier(3);
示例PHP脚本
<?php
$conn = new mysqli("localhost", "foo_dbo", "pass", "foo_db", 3306);
$result = $conn->query(sprintf("call employees_hier(%d)", 1));
while($row = $result->fetch_assoc()){
echo sprintf("#%s %s -> #%s %s<br/>", $row["emp_id"],$row["emp_name"],
$row["boss_emp_id"], $row["boss_name"]);
}
$result->close();
$conn->close();
?>
MySQL脚本
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 employees_hier(1);