1

У меня есть код, который я использовал в SQL Server для создания таблицы замыкания из другой таблицы с прямыми родительскими/дочерними отношениями, я могу запускать очень простые запросы против этого, чтобы определить линию. Теперь я необходимость делать все это в MySql, но у меня возникли проблемы с рекурсивными запросами для создания таблицы закрытия ...таблица транзитных замыканий mySQL

Моего исходного запрос SQL сервера

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 

Моей первой задача состоит в поиске подстановка для @@ 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

Смежные вопросы