我有一个应用程序,其中包含任务,您可以重新排序它们.现在我想知道如何最好地存储它们.我是否应该为ordernumber设置colomn并在每次更改时重新计算所有这些?请告诉我一个不需要我更新所有订单号的版本,因为这非常耗时(从执行的角度来看).
如果我必须将一个位于订单顶部然后将其拖到底部,那么这尤其糟糕.
名称(订单号)
-
1例(1)
2例子(2)
3例3(3)
4例子(4)
5例子(5)
-
2例子(1)*
3例子(2)*
4例3(*)*
5例(4)*
1例(5)*
*必须在数据库中进行更改
一些任务也可能因为完成而被删除
您可以将订单保留为文字,并使用词法排序:
1. A 2. Z
添加任务:
1. A 3. L 2. Z
添加更多:
1. A 4. B 3. L 2. Z
在1和4之间移动2:
1. A 2. AL 4. B 3. L
等等
你一次只更新一条记录:只需要在不同的第一条记录之间取一个平均字母:如果放在A
和之间C
,你可以采取B
,如果放在ALGJ
和之间ALILFG
,你就可以ALH
.
现有计数旁边的字母表示为现有的字母与旁边的字母连接Z
.I. e.如果你需要把它放在ABHDFG
和ACSD
F 之间,你就把它算作介于ABH
和之间AB(Z+)
,然后写AB(letter 35/2)
出来ABP
.
如果您的字符串长度不足,您可能总是执行完整的重新排序.
更新:
您还可以将数据保存为链接列表.
请参阅我的博客中有关如何执行此操作的文章MySQL
:
排序列表
简而言之:
/* This just returns all records in no particular order */ SELECT * FROM t_list id parent ------- -------- 1 0 2 3 3 4 4 1 /* This returns all records in intended order */ SELECT @r AS _current, @r := ( SELECT id FROM t_list WHERE parent = _current ) FROM ( SELECT @r := 0 ) vars, t_list _current id ------- -------- 0 1 1 4 4 3 3 2
移动项目时,您需要更新大多数4
行.
这似乎是保持频繁更新的有序列表的最有效方法.
通常我会按照你的建议添加一个名为'Ordinal'或'PositionOrdinal'的int或smallint列,并且你提到的确切警告 - 每次重新记录单个记录时需要更新可能有意义的记录数订购.
好处是,给定特定任务的密钥和该任务的新位置,移动项目的代码只是两个语句:
UPDATE `Tasks` SET Ordinal= Ordinal+1 WHERE Ordinal>=@NewPosition UPDATE `Tasks` SET Ordinal= @NewPosition WHERE TaskID= @TaskID
对于双向链表或词汇顺序还有其他建议.两者都可以更快,但代价是更复杂的代码,而性能只会在同一组中有很多项目时才会起作用.
性能或代码复杂性是否更重要取决于您的情况.如果您有数百万条记录,那么额外的复杂性可能是值得的.但是,我通常更喜欢更简单的代码,因为用户通常只手动订购小型列表.如果列表中没有那么多项,则额外更新无关紧要. 这通常可以处理数千条记录,而不会对性能产生任何明显影响.
更新示例时要记住的一件事是该列仅用于排序,而不是直接显示给用户.因此,当将项目从顶部拖动到底部时,如图所示,您需要更改的唯一内容是一条记录.你将第一个位置留空并不重要.这意味着通过足够的重新排序来溢出整数排序的可能性很小,但让我再说一遍:用户通常只能手动订购小型列表.我从来没有听说过这种风险实际上导致了问题.