Вопрос

У меня есть база данных "список задач", которая использует модель списка смежности (см. Ниже), поэтому каждая "задача" может иметь неограниченное количество подзадач.В таблице есть столбец "TaskOrder", поэтому все отображается в правильном порядке в treeview.

Существует ли инструкция SQL (MS-SQL 2005), которая выберет все дочерние узлы для указанного родительского узла и обновит столбец TaskOder при удалении родственного узла?

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

Есть какие-нибудь идеи?Спасибо.

Это было полезно?

Решение

Пара разных способов...Поскольку область действия TaskOrder ограничена родительским идентификатором, собрать его не так уж сложно.В SQL Server я бы поставил триггер на удаление, который уменьшает все значения "выше", чем тот, который вы удалили, тем самым закрывая пробел (далее следует псевдокод):

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

Если вам не нужен триггер, вы можете сначала захватить ParentID и TaskOrder в запросе, удалить строку, затем выполнить тот же оператор update, но с литералами, а не с триггером.

Или, если вы хотите свести к минимуму обходы сервера туда и обратно, вы могли бы переместить задачу, подлежащую удалению, до самого низа, затем переместить остальные вверх, затем выполнить удаление, но это кажется чрезмерно сложным.

Другие советы

Если вы используете TaskOrder только для сортировки, безусловно, было бы проще просто оставить пробелы в TaskOrder, потому что простое удаление элементов не сделает сортировку неправильной.Но тогда я не уверен в потребностях вашего приложения.

Не напрямую.Это настоящий Топологическая сортировка где вы "подвешиваете" дочерние узлы к родительскому.Если внутри дочерних элементов нет зависимости, порядок их выполнения не имеет значения.Если дочерние элементы должны выполняться в определенном порядке, то у вас недостаточно информации, чтобы сделать такой вывод - они должны были бы иметь дополнительные уровни иерархии.

Предполагая, что порядок дочерних элементов внутри родительского элемента не имеет значения, тогда топологическая сортировка даст вам то, что вы хотите.Вы не получите это в виде отдельного запроса на большинстве диалектов SQL - вам придется написать sproc, чтобы сделать это.

Если порядок дочерних элементов внутри узла релевантен, то вам необходимо сохранить порядок задач внутри родительского узла.Запрос, использующий ParentNodeID, TaskOrder и count (*), выделит дубликаты, но если в системе нет дополнительной информации для упорядочивания задач, вам все равно потребуется ручное вмешательство, чтобы выбрать правильный порядок.

Пожалуйста, добавляйте комментарии, если вы хотите, чтобы я что-то прояснил.

Это похоже на задание для 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

Удалить задачу 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;

Конечно, вы могли бы исключить удаление и просто оставить запись без присмотра для будущих отчетов.

ПРЕДОСТЕРЕЖЕНИЕ:НЕ ПРОВЕРЕНО!!!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top