Consulta de selección de MySQL

Tengo una gran cantidad de datos de empleados en mysql con un atributo como identificación principal que almacena el supervisor de cada empleado y está definido en una jerarquía. Cada usuario trabaja con otro empleado y maneja un equipo de 4-5 miembros. Con frecuencia necesito el árbol de supervisores o subordinados para el que estoy usando una función recursiva para buscar un empleado con su equipo. Sugiérame un método para que no tenga que llamar a la función recursiva cada vez que necesite datos de empleados. ¿Es una buena idea utilizar "Vistas o procedimiento almacenado"?

Gracias.

preguntado el 09 de enero de 11 a las 10:01

¿Por qué, realmente le está dando problemas de rendimiento hacer la consulta cada vez? Suena difícil de creer si son solo unas pocas docenas de discos. -

Pero tal vez valga la pena mirar la caché de consultas mySQL (si aún no está activa): dev.mysql.com/doc/refman/5.1/en/query-cache.html -

¿Quiere decir que necesita buscar todo el árbol para un empleado, o solo la siguiente sección superior o del árbol? -

¿Qué ocurre en 4-5 búsquedas de claves primarias? -

@Pekka No tengo solo docenas de registros. Tengo miles de empleados en mi base de datos. -

3 Respuestas

Cuando utilice procedimientos almacenados, aún necesitará la recursividad. Solo mueve la recursividad del código fuente PHP a la base de datos.

Puedes usar conjuntos anidados para almacenar datos jerárquicos. Esto elimina las recursiones a costa de mayores costos de inserción, eliminación y reubicación. Básicamente, creas dos campos adicionales left y right dónde left < right y e1 es subordinado de e2 si e1.left > e2.left && e1.right < e2.right.

Esto hace que las consultas SELECT sean difíciles de leer, pero eficientes. Haga esto cuando todo lo demás falle.

Respondido el 09 de enero de 11 a las 14:01

Muchas gracias Sr. Oswald, por favor escríbame un pequeño código detallado. - Umar Adil

Gracias señor, recibí su concepto de este enlace dev.mysql.com/tech-resources/articles/hierarchical-data.html - Umar Adil

Lo siento, acepté esta respuesta tarde, ya que hoy me he enterado de ella: Umar Adil

@Umar (y cualquiera que lea esto): Nueva dirección de este artículo: mikehillyer.com/articles/managing-hierarchical-data-in-mysql - Paŭlo Ebermann

Aquí hay una implementación de procedimiento almacenado no recursivo que obviamente solo requiere una llamada del código de su aplicación, no n llamadas (una para cada nivel del árbol). Recomendaría mantenerse alejado de los conjuntos anidados y seguir con la implementación de la lista de adyacencia; piense conectarse por Oracle y CTE en el servidor sql - no digas más.

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

Respondido el 09 de enero de 11 a las 14:01

no hay problemas: un día (dedos cruzados) mysql tendrá CTE o se conectará por funcionalidad, lo que hará que la lista de adj vs el argumento del conjunto anidado sea discutible. - Jon Black

contestado el 23 de mayo de 17 a las 13:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.