かなり簡単な非再帰的な隣接リストのストアドプロシージャの実装階層。
mysql> call employees_hier(1);
+--------+-----------------+-------------+-----------------+-------+
| emp_id | emp_name | boss_emp_id | boss_name | depth |
+--------+-----------------+-------------+-----------------+-------+
| 1 | f00 | NULL | NULL | 0 |
| 2 | ali later | 1 | f00 | 1 |
| 3 | megan fox | 1 | f00 | 1 |
| 4 | jessica alba | 3 | megan fox | 2 |
| 5 | eva longoria | 3 | megan fox | 2 |
| 6 | keira knightley | 5 | eva longoria | 3 |
| 7 | liv tyler | 6 | keira knightley | 4 |
| 8 | sophie marceau | 6 | keira knightley | 4 |
+--------+-----------------+-------------+-----------------+-------+
8 rows in set (0.00 sec)
明らか
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);
が入れ子集合というhttp://dev.mysql.com/tech-resources/articles/hierarchical-data.html –
注意を参照してください...あなたのカテゴリを従業員に置き換えますモデルは検索には最適ですが、更新は隣接リストモデルよりもはるかに多くの作業が必要です。さらに、この記事で紹介した唯一の更新アルゴリズムはノードの追加と削除ですが、時々はサブツリー全体を移動したいこともあります。 –
それは読み込みにはそれほど素晴らしいものではありません。 –