Encontrar migas de pan para conjuntos anidados
Estoy usando conjuntos anidados (también conocido como recorrido de árbol de pedido anticipado modificado) para almacenar una lista de grupos, y estoy tratando de encontrar una forma rápida de generar migas de pan (como una cadena, no una tabla) para TODOS los grupos a la vez . Mis datos también se almacenan utilizando el modelo de lista de adyacencia (hay activadores para mantener los dos sincronizados).
Así por ejemplo
ID Name ParentId Left Right
0 Node A 0 1 12
1 Node B 0 2 5
2 Node C 1 3 4
3 Node D 0 6 11
4 Node E 3 7 8
5 Node F 4 9 9
Que representa el árbol:
Nodo ANodo BNodo CNodo DNodo ENodo FMe gustaría poder tener una función definida por el usuario que devuelva una tabla:
ID Breadcrumb
0 Node A
1 Node A > Node B
2 Node A > Node B > Node C
3 Node A > Node D
4 Node A > Node D > Node E
5 Node A > Node D > Node F
Para hacer esto un poco más complicado (aunque está fuera del alcance de la pregunta), también tengo restricciones de usuario que deben respetarse. Entonces, por ejemplo, si solo tengo acceso a id = 3, cuando ejecuto la consulta debería obtener:
ID Breadcrumb
3 Node D
4 Node D > Node E
5 Node D > Node F
Tengo una función definida por el usuario que toma un ID de usuario como parámetro y devuelve una tabla con los ID de todos los grupos que son válidos, siempre y cuando en algún lugar de la consulta
WHERE group.id IN (SELECT id FROM dbo.getUserGroups(@userid))
funcionará
Tengo una función escalar existente que puede hacer esto, pero simplemente no funciona en un número razonable de grupos (toma> 10 segundos en 2000 grupos). Toma un groupid y userid como parámetro, y devuelve un nvarchar. Encuentra los grupos de padres dados (1 consulta para tomar los valores izquierdo / derecho, otra para encontrar los padres), restringe la lista a los grupos a los que el usuario tiene acceso (usando la misma cláusula WHERE que la anterior, por lo que otra consulta), y luego usa un cursor para pasar por cada grupo y agregarlo a una cadena, antes de finalmente devolver ese valor.
Necesito un método para hacerlo que se ejecute rápidamente (por ejemplo, <= 1s), sobre la marcha.
Esto está en SQL Server 2005.