用于处理数据库中可排序项的高效且正确的策略

时间:2011-01-06 00:23:26

标签: algorithm sorting database-design

在Web应用程序中,我在数据库中有一组实体,其数字字段负责其排序。在客户端,这些实体显示为可排序列表,允许用户更改其订单。

截至目前,我有两个管理订单更新的解决方案,但没有一个能让我满意。

第一个很简单:每次用户更改某个项目顺序时,遍历更新列表,将所有项目ID转换为数组,将其发送到服务器并发出一系列更新,其中每个项目顺序是它在数组中的ID索引。
这种方法的缺点:许多不必要的更新,无法正确处理发送到服务器的项目数组不包含所有实体ID时的情况。

第二个如下:当用户更改项目订单时,更改项目的ID将与ID中的项目ID一起发送到服务器,这些项目位于列表中新位置的“已更改项目”。在服务器项目上,新订单由(previous.order + next.order) / 2计算。因此,如果订单3的项目在订单5和6的项目之间移动,则新订单将变为5.5
该解决方案的每只需改变一次更新,但也有一个严重的问题:由于使用的每一个变化的算法,以数字增加了小数部分,迟早需要更多精密然后我的数据库可以提供(我使用MongoDB的这种情况,但我想这并不重要。)

我的问题是,是否存在任何其他更有效和正确的方法,或者我现在的方法可能会以某种方式得到改善?

3 个答案:

答案 0 :(得分:5)

使用序号描述数据库中的顺序,该序号从第一项开始为0,对于每个后续项开始增加1。然后,您只需要发送已移动项目的序号,以及新上一个邻居的序号。然后你做(我用$来标记变量 - 你需要将它们传递给代码中的查询):

-- if $moved > $previous, and it's moving backwards, move everything between the new previous neighbour and the item forward one
update items
set ordinal = ordinal + 1
where ordinal > $previous
and ordinal < $moved;

-- else $moved < $previous, and it's moving forwards, move everything between the item and the new previous neighbour backwards one
update items
set ordinal = ordinal - 1
where ordinal > $moved
and ordinal <= $previous;

-- then move the item
update items
set ordinal = $previous + 1
where ordinal = $moved;

您可以为序数列添加唯一约束以帮助确保完整性,但您必须更加清楚地了解更新方式。

答案 1 :(得分:1)

我做了类似于你的第二种方法。虽然不是使用双打,但我使用整数并将项目间隔1000.这在我的应用程序中适用于我,因为项目数量不会超过4M。稍后,当我确定增量现在已降至1(或小的某个)时,我会发出一个重置命令,将间隔重置为1000。我是用TSQL做的。

希望这有帮助!

答案 2 :(得分:1)

您可以在数据库中使用链接列表: 丢失订单栏,并在该行上存储先前的商品ID或下一个商品ID 然后更新是微不足道的(但显示已排序的列表的额外工作)。