2011-01-09 12 views
0

Ich habe eine riesige Mitarbeiterdaten in MySQL mit einem Attribut als Eltern-ID, die den Vorgesetzten für jeden Mitarbeiter speichert und in einer Hierarchie definiert ist. Jeder Benutzer arbeitet unter anderem Mitarbeiter und bearbeitet Team von 4-5 Mitgliedern. Ich brauche häufig den Supervisor- oder Untergebenenbaum, für den ich eine rekursive Funktion verwende, um eine Beschäftigung mit seinem Team zu holen. Bitte schlagen Sie mir eine Methode vor, damit ich nicht jedes Mal, wenn ich Mitarbeiterdaten brauche, eine rekursive Funktion aufrufen muss. Ist die Verwendung von "Views oder Stored Procedure" eine gute Idee?MySQL Abfrage auswählen

Danke.

+0

Warum ist es Ihnen Performance-Probleme wirklich zu geben, jedes Mal die Abfrage zu tun? Klingt schwer zu glauben, wenn es nur ein paar Dutzend Datensätze sind. –

+0

Aber vielleicht ist der mySQL-Abfragecache es wert, betrachtet zu werden (wenn er nicht bereits aktiv ist): http://dev.mysql.com/doc/refman/5.1/en/query-cache.html –

+0

Meinen Sie, dass Sie müssen Holen Sie den gesamten Baum für einen Mitarbeiter oder nur den nächsthöheren oder den Baumabschnitt? –

Antwort

0

Wenn Sie gespeicherte Prozeduren verwenden, müssen Sie noch Rekursion verwenden. Sie verschieben die Rekursion nur vom PHP-Quellcode in die Datenbank.

Sie können nested sets verwenden, um hierarchische Daten zu speichern. Dadurch werden Rekursionen zum Preis von höheren Kosten für Einfügen, Löschen und Verlagerung vermieden. Grundsätzlich erstellen Sie zwei zusätzliche Felder left und right, wobei left < right und e1e2 iff e1.left > e2.left && e1.right < e2.right untergeordnet ist.

Dies macht SELECT-Abfragen schwer zu lesen, aber effizient. Tun Sie dies, wenn alles andere fehlschlägt.

+0

Vielen Dank Herr Oswald, bitte schreiben Sie mir einen kleinen detaillierten Code. –

+0

Danke Herr, ich habe Ihr Konzept von diesem Link http://dev.mysql.com/tech-resources/articles/hierarchical-data.html –

+0

Sorry, ich akzeptierte diese Antwort spät, als ich heute darüber –

2

Hier ist eine nicht rekursive Stored Procedure-Implementierung, die offensichtlich nur einen Aufruf von Ihrem Anwendungscode nicht n Aufrufe (einen für jede Ebene der Struktur) erfordert. Würde empfehlen, weit weg von verschachtelten Sets zu bleiben und bei Ihnen Adjazenz Liste Implementierung zu bleiben - denken verbinden von Oracle und CTE in SQL Server - sagen nicht mehr.

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

Vielen Dank, Lemme versuchen Sie es Ich hoffe, das funktioniert für mich. :) –

+0

keine probs - ein Tag (Daumen drücken) mysql wird CTE oder verbinden durch Funktionalität, die die adj-Liste vs verschachtelte Menge Argument macht. –

Verwandte Themen