Tho*_*aaf 12 mysql sorting database-design
我有一个应用程序,其中包含任务,您可以重新排序它们.现在我想知道如何最好地存储它们.我是否应该为ordernumber设置colomn并在每次更改时重新计算所有这些?请告诉我一个不需要我更新所有订单号的版本,因为这非常耗时(从执行的角度来看).
如果我必须将一个位于订单顶部然后将其拖到底部,那么这尤其糟糕.
-
-
*必须在数据库中进行更改
一些任务也可能因为完成而被删除
Qua*_*noi 14
您可以将订单保留为文字,并使用词法排序:
1. A
2. Z
Run Code Online (Sandbox Code Playgroud)
添加任务:
1. A
3. L
2. Z
Run Code Online (Sandbox Code Playgroud)
添加更多:
1. A
4. B
3. L
2. Z
Run Code Online (Sandbox Code Playgroud)
在1和4之间移动2:
1. A
2. AL
4. B
3. L
Run Code Online (Sandbox Code Playgroud)
等等
你一次只更新一条记录:只需要在不同的第一条记录之间取一个平均字母:如果放在A和之间C,你可以采取B,如果放在ALGJ和之间ALILFG,你就可以ALH.
现有计数旁边的字母表示为现有的字母与旁边的字母连接Z.I. e.如果你需要把它放在ABHDFG和ACSDF 之间,你就把它算作介于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
Run Code Online (Sandbox Code Playgroud)
移动项目时,您需要更新大多数4行.
这似乎是保持频繁更新的有序列表的最有效方法.
通常我会按照你的建议添加一个名为'Ordinal'或'PositionOrdinal'的int或smallint列,并且你提到的确切警告 - 每次重新记录单个记录时需要更新可能有意义的记录数订购.
好处是,给定特定任务的密钥和该任务的新位置,移动项目的代码只是两个语句:
UPDATE `Tasks` SET Ordinal= Ordinal+1 WHERE Ordinal>=@NewPosition
UPDATE `Tasks` SET Ordinal= @NewPosition WHERE TaskID= @TaskID
Run Code Online (Sandbox Code Playgroud)
对于双向链表或词汇顺序还有其他建议.两者都可以更快,但代价是更复杂的代码,而性能只会在同一组中有很多项目时才会起作用.
性能或代码复杂性是否更重要取决于您的情况.如果您有数百万条记录,那么额外的复杂性可能是值得的.但是,我通常更喜欢更简单的代码,因为用户通常只手动订购小型列表.如果列表中没有那么多项,则额外更新无关紧要. 这通常可以处理数千条记录,而不会对性能产生任何明显影响.
更新示例时要记住的一件事是该列仅用于排序,而不是直接显示给用户.因此,当将项目从顶部拖动到底部时,如图所示,您需要更改的唯一内容是一条记录.你将第一个位置留空并不重要.这意味着通过足够的重新排序来溢出整数排序的可能性很小,但让我再说一遍:用户通常只能手动订购小型列表.我从来没有听说过这种风险实际上导致了问题.
我建议在数据库中有一个订单列。对对象进行重新排序时,请在数据库中重新排序的对象和具有相同顺序值的对象之间交换顺序值,这样您就不必对整个行集进行重新排序。
希望这是有道理的......当然,这取决于您的重新排序规则。