2010-11-22 11 views
1

私はSQL Serverで直接親子関係のある別のテーブルからクロージャーテーブルを生成するためのコードをいくつか持っています。今、私のオリジナルのSQL Serverクエリが私の最初の問題が発見されmySQL推移閉包テーブル

WHILE @@ROWCOUNT>0 
INSERT INTO [ClosureTable] ([Ancestor], [Descendent]) 
SELECT distinct [Parent],[tc].[Descendent] 
FROM 
    [RelationshipTable] 
INNER JOIN [ClosureTable] as tc 
    ON [Child]COLLATE DATABASE_DEFAULT = 
         [tc].[Ancestor]COLLATE DATABASE_DEFAULT 
LEFT OUTER JOIN [ClosureTable] As tc2 
    ON [Parent]COLLATE DATABASE_DEFAULT = 
         [tc2].[Ancestor] COLLATE DATABASE_DEFAULT 
    AND [tc].[Descendent]COLLATE DATABASE_DEFAULT = 
         [tc2].[Descendent]COLLATE DATABASE_DEFAULT 

です...

を私はMySQLですべてこれを行うために必要とするのですが、私は、閉鎖テーブルを生成するために、再帰クエリに問題が生じています@@ ROWCOUNTの代入文ですが、おそらく再帰的なクエリはmySQLではまったく異なりますか?私もチェックアウトしましたBill Karwin's presentation

PS。 "COLLATE DATABASE_DEFAULT"は、パフォーマンスの問題のために必要なものでした。

ありがとうございました。私はそれが周りに再帰的に隣接リストテーブルからツリーを生成すると思う - - 私はあなたの正確な問題が何であるかを理解している場合

答えて

0

わからない場合は、次のように助けるかもしれないが、それは再帰的ではありません(何の恥!)

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); 
+0

更新: ありがとう。私は明日これをもう一度見ます。今は疲れています...また、私はhttp://mondrian.pentaho.com/documentation/schema.php#Closure_tablesで有望なコードを見つけましたが、繰り返しループに問題があります。 – DougF

2

私はこれが古いですけど、私はあなたがまだ見て他の人のために、この上で答えを必要とする感じが、ここで私は私の標準隣接テーブルから私の閉鎖テーブルを生成する方法である:

mysql_query('TRUNCATE fec_categories_relations'); 

function rebuild_tree($parent) 
{ 
    // get all children of this node 
    $result = mysql_query('SELECT c.categories_id, c.parent_id, cd.categories_name FROM fec_categories c 
          INNER JOIN fec_categories_description cd ON c.categories_id = cd.categories_id 
          WHERE c.parent_id = "'.$parent.'" 
          AND  cd.language_id = 1 
          ORDER BY cd.categories_name'); 

    // loop through 
    while ($row = mysql_fetch_array($result)) 
    {  
     $update_sql = " INSERT fec_categories_relations (ancestor, descendant, length) 
         SELECT ancestor, {$row['categories_id']}, length+1 
         FROM fec_categories_relations 
         WHERE descendant = {$row['parent_id']} 
         UNION ALL SELECT {$row['categories_id']},{$row['categories_id']}, 0"; 

     mysql_query($update_sql); 

     echo '<li>' . $update_sql . "</li>"; 

     rebuild_tree($row['categories_id']); 
    } 
} 

rebuild_tree(0); 
+0

遅れた応答の伝統で...ありがとう。私はこれに亀裂を与えるでしょう。私は実際にそれを解決することに終わった、ちょうど一緒に答えを得る機会を持っていない。私は次のカップルの日にあなたの答えをチェックしますので、私はこの質問を閉じることができます - データベースではなく、PHPでこれをすべて行います。ありがとう。 – DougF