我有一個使用鄰接列表模型的「任務列表」數據庫,因此每個「任務」可以有無限的子任務。該表有一個'TaskOrder'列,所以在樹視圖中所有東西都以正確的順序呈現。SQL對層次中的節點進行重新排序
是否有SQL語句(MS-SQL 2005)將選擇指定父級的所有子節點並在刪除兄弟級別時更新TaskOder列?
Task Table ---------- TaskId ParentTaskId TaskOrder TaskName --etc--
任何想法?謝謝。
我有一個使用鄰接列表模型的「任務列表」數據庫,因此每個「任務」可以有無限的子任務。該表有一個'TaskOrder'列,所以在樹視圖中所有東西都以正確的順序呈現。SQL對層次中的節點進行重新排序
是否有SQL語句(MS-SQL 2005)將選擇指定父級的所有子節點並在刪除兄弟級別時更新TaskOder列?
Task Table ---------- TaskId ParentTaskId TaskOrder TaskName --etc--
任何想法?謝謝。
幾種不同的方式...由於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,然後刪除該行,然後執行相同的更新語句,但使用文本而不是觸發器。
或者,如果您希望儘量減少服務器往返次數,您可以將待刪除的任務一直移動到底部,然後移動其他任務,然後執行刪除操作,但看起來過於複雜。
如果您只使用TaskOrder進行排序,那麼只需簡單地在TaskOrder中留下空位,因爲只需刪除項目就不會使排序錯誤。但是,我不確定您的應用程序的需求。
不是直接。這是一個Topological Sort,您將子節點「懸掛」在父母身上。如果孩子中沒有依賴關係,他們執行的順序並不重要。如果孩子必須以某種順序執行,那麼你沒有足夠的信息來推斷這一點 - 他們將不得不有更多的層次。
假設父母中的孩子的順序是不相關的,那麼topoligical排序會讓你得到你想要的。你不會在大多數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;
當然,你可以消除刪除,並且只留下躺在身邊以備將來報告目的的記錄。
CAVEAT:NOT TESTED !!!