我有一个使用邻接列表模型的“任务列表”数据库(见下文),因此每个“任务”都可以拥有无限的子任务。该表有一个'TaskOrder'列,因此所有内容都在树视图上以正确的顺序呈现。
是否有SQL语句(MS-SQL 2005)将为指定的父节点选择所有子节点,并在删除兄弟节点时更新TaskOder列?
Task Table ---------- TaskId ParentTaskId TaskOrder TaskName --etc--
有什么想法吗?感谢。
答案 0 :(得分:2)
如果您只使用TaskOrder进行排序,那么简单地在TaskOrder中留下漏洞肯定会更简单,因为简单地删除项目不会使排序不正确。但后来我不确定你的应用程序的需求。
答案 1 :(得分:1)
几种不同的方式......由于TaskOrder的范围是父ID,所以收集它并不是非常困难。在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,删除该行,然后用文字而不是触发器执行相同的更新语句。
或者如果你想最小化服务器往返,你可以将待删除的任务一直移到底部,然后移动其他任务,然后执行删除,但这似乎过于复杂。
答案 2 :(得分:0)
不直接。这是Topological Sort,您将子节点“挂起”父节点。如果子项中没有依赖项,则执行它们的顺序无关紧要。如果必须以某种顺序执行子项,那么您没有足够的信息来推断它 - 它们必须具有其他级别的层次结构。
假设父母中的孩子的顺序无关紧要,那么拓扑排序将为您提供所需的内容。在大多数SQL方言中,您不会将其转换为单个查询 - 您必须编写一个sproc来执行此操作。
如果节点中子节点的顺序相关,则需要在父节点内维护任务顺序。使用ParentNodeID,TaskOrder和count(*)的查询将选择重复项,但除非系统有其他信息来订购任务,否则仍需要手动干预才能选择正确的顺序。
如果您想让我澄清一些事情,请添加评论。
答案 3 :(得分:0)
这看起来像是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
答案 4 :(得分:0)
删除任务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;
当然,您可以取消删除,只留下记录,以备将来报告。
CAVEAT:没有测试!!!