Tengo una tabla que contiene etapas y subpares de ciertos proyectos, y una tabla con tareas específicas y costos estimados.
Necesito alguna forma de agregar cada nivel (etapas/subpares), para ver cuánto cuesta, pero hacerlo a un costo de rendimiento mínimo.Optimización de la agregación de datos de la rama de árbol en SQL Server 2008 (recursión)
Para ilustrar esto, voy a utilizar la siguiente estructura de datos:
CREATE TABLE stage
(
id int not null,
fk_parent int
)
CREATE TABLE task
(
id int not null,
fk_stage int not null,
cost decimal(18,2) not null default 0
)
con los siguientes datos:
==stage==
id fk_parent
1 null
2 1
3 1
==task==
id fk_stage cost
1 2 100
1 2 200
1 3 600
I desea obtener una tabla que contiene los costes totales de cada rama. Algo como esto:
Stage ID Total Cost
1 900
2 300
3 600
Pero, también quiero que sea productivo. No quiero terminar con soluciones extremadamente malas como The worst algorithm in the world. Quiero decir que este es el caso. En caso de que solicite los datos para todos los artículos en la tabla stage
, con los costos totales, cada costo total se evaluará D
veces, donde D
es la profundidad en el árbol (nivel) en el que se encuentra. Me temo que alcanzaré rendimientos extremadamente bajos con grandes cantidades de datos con muchos niveles.
SO,
que decidí hacer algo que me hizo esta pregunta aquí.
Decidí agregar 2 columnas más a la tabla stage
, para el almacenamiento en caché.
...
calculated_cost decimal(18,2),
date_calculated_cost datetime
...
Así que lo que quería hacer es pasar otra variable dentro del código, un valor datetime
lo que equivale al tiempo en que este proceso se inició (casi única). De esta forma, si la fila stage
ya tiene un date_calculated_cost
que es igual a la que llevo, no me molesto en calcularlo nuevamente, y simplemente devuelvo el valor calculated_cost
.
no podía hacerlo con las funciones (las actualizaciones son necesarias para la mesa stage
, una vez que se calculan los costes)
no podía hacerlo con los Procedimientos (recursión dentro de los cursores en ejecución es un no-go)
I no estoy seguro de que las tablas temporales sean adecuadas porque no permitiría solicitudes simultáneas para el mismo procedimiento (que son las menos probables, pero de todos modos quiero hacerlo de la manera correcta)
No pude encontrar otras formas.
No estoy esperando una respuesta definitiva a la pregunta, pero voy a recompensar cualquier buena idea, y lo mejor será elegida como la respuesta.
Mientras esperaba las respuestas, resolví mi problema (creo). Agregué algunos campos, calculé el "nivel" de la etapa dentro de un disparador, luego ejecuté un cursor contra todas las etapas, ordené descendiendo por el nivel y obtuve los resultados deseados. Todo se hace dentro de una transacción que bloquea todos los recursos, por lo que no se puede modificar ninguna hoja del árbol. Parece que está funcionando, pero necesito finalizar la parte de integración, obtener algunos datos reales y probarlos, luego lo publicaré aquí también. Tus respuestas parecen ser correctas y muy interesantes para mí. Muchas gracias por tu tiempo. – AlexanderMP