Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 处理数据库中可排序项的有效且正确的策略_Algorithm_Sorting_Database Design - Fatal编程技术网

Algorithm 处理数据库中可排序项的有效且正确的策略

Algorithm 处理数据库中可排序项的有效且正确的策略,algorithm,sorting,database-design,Algorithm,Sorting,Database Design,在web应用程序中,我在数据库中有一组实体,其中的数字字段负责它们的排序。在客户端,这些实体显示为可排序列表,允许用户更改其顺序 到目前为止,我有两个管理订单更新的解决方案,但没有一个能让我满意 第一个很简单:每次用户更改某些项目顺序时,遍历更新的列表,将所有项目ID放入数组,将其发送到服务器,并发出一系列更新,其中每个项目顺序都是数组中ID的索引。 这种方法的缺点:大量不必要的更新,无法正确处理发送到服务器的items数组不包含所有实体ID的情况 第二种方法如下:当用户更改项目顺序时,更改项目

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

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

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

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


我的问题是,是否存在其他更有效、更正确的方法,或者我目前的方法是否可以改进?

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

——如果$moved>$previous正在向后移动,则将新的上一个邻居和前一个邻居之间的所有内容向前移动
更新项目
集合序号=序号+1
其中序号>$previous
依次为<$moved;
--else$moved<$previous,并且它正在向前移动,将项目和新的前一个相邻项目之间的所有内容向后移动
更新项目
集合序号=序号-1
其中序号>$moved

依次我做了类似于你第二种方法的事情。我没有使用双精度,而是使用整数,并将项目间隔1000。这在我的应用程序中对我有效,因为项目数量不会超过400万。稍后,当我确定增量现在降到1(或较小的值)时,我会发出一个重置命令,将间隔再次重置为1000。我使用TSQL实现了这一点


希望这有帮助

您可以在数据库中使用链表: 丢失订单列,并在该行存储上一个项目ID或下一个项目ID。

更新很简单(但显示已排序的列表需要额外的工作)。

您可以在数据库中的单个查询中提取已排序的列表,该数据库可以执行递归查询(例如PostgreSQL、Firebird、大多数专有数据库)。我想。@Tom:有趣。我想知道递归查询在数据库中是否比排序列表客户端更有效。这是一个有趣的想法,但我相信它会使每个CRUD操作复杂化很多,所以我还是决定使用序数。
-- 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;