查询在循环中运行

时间:2010-11-02 09:45:38

标签: sql mysql

我遇到了一个严重的问题。

我正在一个数据库中工作,其中一个用户是先前注册用户的孩子。

那个孩子将有另外两个孩子用户。

这是n级

所以我试图找出问题出现的第n级用户的最多父母

现在我使用循环中运行的查询来查找这个,但我知道它很奇怪,一旦级别开始增加,我的数据库服务器就会挂起。

有人请告诉我一些事情。

可以使用存储过程吗?

4 个答案:

答案 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);