2011-07-11 17 views
14

Digamos que tengo una tabla de empleados, con un registro para cada empleado de mi empresa y una columna para el supervisor (como se ve a continuación). Me gustaría preparar un informe, que enumera los nombres y el título de cada paso en una línea de supervisión. por ejemplo, para dick robbins, 1d # 15, me gustaría una lista de cada supervisor en su "cadena de mando", todo el camino hasta el presidente, un gran queso. Me gustaría evitar el uso de cursores, pero si esa es la única forma de hacerlo, está bien.Cómo recorrer un árbol/Trabajar con datos jerárquicos en el código SQL

id fname lname title supervisorid 
1 big  cheese president 1 
2 jim  william vice president 1 
3 sally carr vice president 1 
4 ryan allan senior manager 2 
5 mike miller manager 4 
6 bill bryan manager 4 
7 cathy maddy foreman 5 
8 sean johnson senior mechanic 7 
9 andrew koll senior mechanic 7 
10 sarah ryans mechanic 8 
11 dana bond mechanic 9 
12 chris mcall technician 10 
13 hannah ryans technician 10 
14 matthew miller technician 11 
15 dick robbins technician 11 

Los datos reales probablemente no serán más de 10 niveles de profundidad ... pero prefiero no sólo hacer 10 exterior se une ... Tenía la esperanza de que había algo mejor que eso, y menos involucrados que los cursores

Gracias por cualquier ayuda.

+1

Puede que le interese mi pregunta: http://stackoverflow.com/questions/3471134/how-to-self-join-recursively-in-sql –

+0

Sus datos tienen un pequeño problema, registre la identificación 1 no puede tener supervisor = 1 romperá la tabla CTE – AaA

Respuesta

20

Esto es básicamente un puerto de la respuesta aceptada en mi pregunta a la que me he vinculado en los comentarios OP.

puede utilizar expresiones de tabla común

WITH Family As 
( 
    SELECT e.id, e.supervisorid, 0 as Depth 
    FROM Employee e 
    WHEREid = @SupervisorID 
    UNION All 
    SELECT e2.ID, e2.supervisorid, Depth + 1 
    FROM Employee e2 
     JOIN Family 
      On Family.id = e2.supervisorid 
) 
SELECT* 
FROM Family 

Para más:

Recursive Queries Using Common Table Expressions

+0

¿Cuál es el carácter @ para exactamente? ¿Tiene que proporcionar un parámetro? No estaba claro, pero lo que en última instancia quiero hacer es proporcionar una lista de todos los empleados, y todas sus respectivas "cadenas de mando" ... para cada empleado, no solo uno. ¿Puedes modificar tu consulta para realizar esto? – Albert

+0

El @SupervisorID es si desea tener una persona "raíz" en una cadena. Si quieres todas las cadenas, simplemente suelta la línea de la cláusula where y debería funcionar. –

+1

¡Gracias, esto me ha salvado de días de frustración! – Marton

0

Algunos función recursiva que, o bien devolver el supervisor (si lo hay) o nulo. Podría ser un SP que también se invoca a sí mismo y que usa UNION.

0

Puede que le interese la solución "Ruta Materializada", que desincroniza ligeramente la tabla, pero puede utilizarse en cualquier tipo de base de datos SQL y evita que tenga que realizar consultas recursivas. De hecho, incluso se puede usar en bases de datos sin SQL.

Solo tiene que agregar una columna que contenga toda la ascendencia del objeto. Por ejemplo, la siguiente tabla incluye una columna denominada tree_path:

+----+-----------+----------+----------+ 
| id | value  | parent | tree_path| 
+----+-----------+----------+----------+ 
| 1 | Some Text |  0 |   | 
| 2 | Some Text |  0 |   | 
| 3 | Some Text |  2 |  -2-| 
| 4 | Some Text |  2 |  -2-| 
| 5 | Some Text |  3 |  -2-3-| 
| 6 | Some Text |  3 |  -2-3-| 
| 7 | Some Text |  1 |  -1-| 
+----+-----------+----------+----------+ 

Selección de todos los descendientes del registro con id = 2 es el siguiente:

SELECT * FROM comment_table WHERE tree_path LIKE '-2-%' ORDER BY tree_path ASC 

para construir un árbol, se puede ordenar por tree_path para obtener una matriz que es bastante fácil de convertir a un árbol.

También puede indexar tree_path y el índice se puede usar cuando el comodín no está al principio. Por ejemplo, tree_path LIKE '-2-%' puede usar el índice, pero tree_path LIKE% -2-'` no puede.

Cuestiones relacionadas