Pregunta

Tengo una base de datos de 'lista de tareas' que usa el modelo de lista de adyacencia (ver más abajo) para que cada 'tarea' pueda tener subtareas ilimitadas. La tabla tiene una columna 'TaskOrder' para que todo se muestre en el orden correcto en una vista de árbol.

¿Existe una instrucción SQL (MS-SQL 2005) que seleccionará todos los nodos secundarios para un padre específico y actualizará la columna TaskOder cuando se elimine un hermano?

Task Table
----------
TaskId
ParentTaskId
TaskOrder
TaskName
--etc--

¿Alguna idea? Gracias.

¿Fue útil?

Solución

Un par de formas diferentes ... Dado que el TaskOrder está definido por la identificación principal, no es terriblemente difícil reunirlo. En SQL Server, pondría un desencadenador en la eliminación que disminuye todas las 'más altas' que la que eliminó, cerrando así la brecha (sigue el pseudocódigo):

CREATE TRIGGER ON yourtable FOR DELETE
AS
  UPDATE Task
     SET TaskOrder    = TaskOrder - 1
   WHERE ParentTaskId = deleted.ParentTaskId
     AND TaskOrder    > deleted.TaskOrder

Si no desea un desencadenador, puede capturar el parentID y TaskOrder en una consulta primero, eliminar la fila, luego ejecutar esa misma declaración de actualización pero con literales en lugar del desencadenante.

O si desea minimizar los viajes de ida y vuelta del servidor, puede mover la tarea que se va a eliminar hasta el final, luego mover los demás hacia arriba y luego eliminar, pero eso parece demasiado complicado.

Otros consejos

Si solo está utilizando TaskOrder para ordenar, sin duda sería más simple simplemente dejar los agujeros en TaskOrder, porque simplemente eliminar elementos no hará que la clasificación sea incorrecta. Pero no estoy seguro de las necesidades de su aplicación.

No directamente. Este es un Clasificación topológica donde está 'colgando' los nodos hijos de un padre. Si no hay dependencia dentro de los hijos, no importa el orden en que se ejecutan. Si los hijos deben ejecutarse en un cierto orden, entonces no tiene suficiente información para inferir esto: tendrían que tener niveles adicionales de jerarquía.

Suponiendo que el orden de los hijos dentro de un padre es irrelevante, un tipo topológico le dará lo que desea. No obtendrá esto en una sola consulta en la mayoría de los dialectos de SQL; tendrá que escribir un sproc para hacerlo.

Si el orden de los elementos secundarios dentro del nodo es relevante, entonces debe mantener el orden de las tareas dentro del elemento primario. Una consulta usando ParentNodeID, TaskOrder y count (*) seleccionará duplicados, pero a menos que el sistema tenga información adicional para ordenar las tareas, aún necesitará intervención manual para seleccionar el orden correcto.

Agregue comentarios si desea que aclare algo.

Esto parece un trabajo para ROW_Number.

DECLARE @Tasks TABLE
(
  TaskId int PRIMARY KEY,
  ParentTaskId int,
  TaskOrder int,
  TaskName varchar(30)
)

INSERT INTO @Tasks(TaskId, ParentTaskId, TaskOrder, TaskName)
SELECT 1, null, 1, 'ParentTask'

INSERT INTO @Tasks(TaskId, ParentTaskId, TaskOrder, TaskName)
SELECT 2, 1, 2, 'B'

INSERT INTO @Tasks(TaskId, ParentTaskId, TaskOrder, TaskName)
SELECT 3, 1, 1, 'A'

INSERT INTO @Tasks(TaskId, ParentTaskId, TaskOrder, TaskName)
SELECT 4, 1, 3, 'C'
--Initial
SELECT * FROM @Tasks WHERE ParentTaskId = 1 ORDER BY TaskOrder

DELETE FROM @Tasks WHERE TaskId = 2
--After Delete
SELECT * FROM @Tasks WHERE ParentTaskId = 1 ORDER BY TaskOrder


UPDATE t
SET TaskOrder = NewTaskOrder
FROM @Tasks t
  JOIN
(
SELECT TaskId, ROW_Number() OVER(ORDER BY TaskOrder) as NewTaskOrder
FROM @Tasks
WHERE ParentTaskId = 1
) sub ON t.TaskId = sub.TaskId

--After Update
SELECT * FROM @Tasks WHERE ParentTaskId = 1 ORDER BY TaskOrder

Eliminar tarea 88:

UPDATE TaskTable
SET ParentTaskID = (SELECT ParentTaskID AS temp FROM Task_Table t1 WHERE TaskID = 88)
WHERE
TaskID IN (SELECT TaskID task2 FROM TaskTable t2 WHERE ParentTaskID = 88);
Delete FROM TaskTable WHERE TaskID = 88;

Por supuesto, puede eliminar la eliminación y dejar el registro por ahí para futuros informes.

PRUEBA: ¡NO SE PRUEBA!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top