存储在数据库中的任务的优先级列表


9

我正在尝试执行以下操作的最佳方法:

我有一个存储在数据库中的任务列表。任务具有分配的优先级。您可以更改任务的优先级,以重新排序执行任务的顺序。

我在想与Pivotal Tracker非常相似的东西。

因此,假设我们有以下内容:

1 Task A
2 Task B
3 Task C
4 Task D
5 Task E

我们认为E现在是最重要的任务

1 Task E
2 Task A
3 Task B
4 Task C
5 Task D

我需要更新所有5个任务以赋予它们新的优先级。

如果任务B变得更加重要,那么我将拥有AI

1 Task E
2 Task B
3 Task A
4 Task C
5 Task D

我只需要更新任务B和A。

在数据库中构造该结构有哪些方法?我想您会在同一张表中存储不同的项目,这些项目将具有自己的权重。

最好指出一个在它之后发生的任务(有点像一个链接列表)。

真的,这真是个大难题。只是想知道您将如何实施这样的事情。

Answers:


6
  1. 看起来您正在寻找优先级队列。您可能不应该重新计算任务的优先级数字,而应该为它们计算一个固定值。如果您希望任务E更重要,请降低它的价值。
  2. 您实质上是在谈论关系。B应该比A更重要。E应该是最重要的任务,等等。这听起来像树结构,您可以将其存储在带有父链接的RDBMS中。

5

如果使用双浮点数表示优先级,则无需重新排序:

1.00 Task A
2.00 Task B
3.00 Task C
4.00 Task D
5.00 Task E

如果要将任务E放在A和B之间,则:-

  E.priority = A.priority + ((B.priority - A.priority) / 2)

现在,您有了:

1.00 Task A
1.50 Task E
2.00 Task B
3.00 Task C
4.00 Task D

如果要在E和B之间插入D,则只需将其优先级设置为1.75。鉴于浮点数中大约有18个十进制数字(1.75实际上是1.7500000000000000),在以下情况下,应该有53次连续插入的最坏情况:

 A.priority + ((B.priority - A.priority) / 2) = B.priority

在有人抱怨使用双精度数与整数的开销之前,它只需要几个硬件指令,而在数据库中对列表进行重新排序的处理和I / O开销则要大几个数量级。


1
我喜欢这种方法,但应该是:E.priority = A.priority +(((B.priority-A.priority)/ 2)和A.priority +((B.priority-A.priority)/ 2)= B.priority
Marcel Panse

感谢您指出了这一点-回答相应的修改
詹姆斯-安德森

1

我们做了您正在谈论的事情。我们通过使用一个对项目列表重新排序的存储过程来做到这一点。列表中的每个项目都有一个唯一的ID和一个排序顺序号。

例如:

TaskId int identity(1,1),
Task varchar(50),
SortOrder int

对项目重新排序的存储过程采用两个输入参数:

@TaskId int,
@NewSortOrder int

我们使用了一个临时表来存储新订单中的项目:

CREATE TABLE #Tasks
(
RowId int identity(1,1),
TaskId int
)

我们使用了三个选择语句使它们进入新顺序:

-- Step 1
INSERT INTO #Tasks
SELECT TaskId FROM tblTasks
WHERE SortOrder < @NewSortOrder
ORDER BY SortOrder

--Step 2
INSERT INTO #Tasks
VALUES(@TaskId)

--Step 3
INSERT INTO #Tasks
SELECT TaskId FROM tblTasks
WHERE SortOrder >= @NewSortOrder
ORDER BY SortOrder

然后,我们使用新的排序顺序更新了基表(tblTask​​s),该排序顺序实际上是临时表的RowId标识列:

-- Update Base Table
UPDATE tblTasks
SET SortOrder = t2.RowId
FROM tblTasks t1
INNER JOIN #Tasks t2
ON t1.TaskId = t2.TaskId

每次都像冠军。


0

我还没有考虑到这一点.....但是为什么不只允许小数,这样您就可以在彼此之间填充内容而无需更新所有内容?

您可以将值压缩为1到2之间的值1.5。

我也要避免最小值和最大值。如果数字优先于当前为0的数字,则允许它们滚入负数。

您可以考虑将“人为显示”优先级与内部“排序”优先级分开,以避免显示奇怪的小数和负值。


不要使用小数。使用数字或字母字符串。然后,您始终可以在两个旧值之间插入一个新值,至少直到达到字符串长度限制为止。
凯文·克莱恩

0

在RDBMS中实现链接列表及其操作是非常合理的。只需用SQL查询替换数组和引用操作即可。但是,我不确定这是否真的是最有效的方法,因为一些简单的操作将需要许多SQL查询

对于任务表,您将列“ next_task”和“ prev_task”添加为同一表的id列的外键(假设“ -1”等效于NULL)

返回带有highest_priority()的任务:SQL查询返回带有prev_task = -1的任务

E是最重要的任务:SQL查询,它将E的next_task更改为优先级最高的任务的ID。并将E的prev_task更改为-1 ...

此操作和其他操作(例如将E放在A之前或打印任务的有序列表)将需要更多的SQL查询,这些查询应该都是原子的(除非您能够进行优化)。这是一个很好的练习,但可能不是最有效的方法。


0

解决优先级问题的另一种方法是指定哪个项目比该项目更重要。在人力资源应用程序中,这就像说出雇员的经理是谁。

ID  Name           ParentPriority
1   TopPriority    NULL
2   Medium         1
3   Low            2
4   AnotherMedium  1
5   Less than 2    2

然后阅读此http://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-recursive-cte-a-primer/进行优先级查询水平。

ID  Name           ParentPriority  PriorityLevel
1   TopPriority    NULL            1
2   Medium         1               2
3   Low            2               3
4   AnotherMedium  1               2
5   Less than 2    2               3

我认为在设置优先级时这是一种较简单的用户体验,但是它确实允许同一级别的多个优先级。


-1

一种简单的方法是从这样的东西开始:

100 Task A
200 Task B
300 Task C
400 Task D
500 Task E

然后,例如,要在任务A和任务B之间移动“任务E”,您只需将“任务E”的优先级设置为任务A和任务B之间的一半(在本例中为“ 150”)。

当然,如果您不断重新安排优先级,最终将遇到一个问题,即两个相邻的任务之间没有“间隙”以插入新条目。但是,当发生这种情况时,您可以简单地“重置”所有优先级,一次回到100、200、300等。


1
这实际上与我的答案相同,只是以较大的整数而不是紧密分组的小数开始。:)
jojo 2011年

-1

我不是数据库专家,所以我以Access 2010中最合理的方式解决了此问题。我有一个“优先级”字段,它是一个数字字段。然后,我有一个针对该领域的活动。

该事件是字段“ Priority”的更新后事件,该事件触发更新查询“ qryPriority”,以向优先级大于或等于刚输入的优先级的所有其他记录的优先级数加1。

这是事件VB代码和更新查询SQL:

“优先”事件VB代码:

Private Sub Priority_AfterUpdate()
Me.Refresh
If Priority > 0 Then
DoCmd.OpenQuery ("qryPriority")
End If
Me.Refresh
Priority = Priority - 1
End Sub

“ qryPriority”更新查询SQL:

UPDATE YOURTABLENAME SET YOURTABLENAME.Priority = [Priority]+1
WHERE (((YOURTABLENAME.Priority)>=[Forms]![YOURFORMNAME]![Priority]));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.