在数据库表中使用sorting顺序列

比方说,我在购物网站的数据库中有一个Product表,以保存商店产品的描述,价格等。 使客户能够重新订购这些产品的最有效方法是什么?

我创build了一个Order列(整数)用于sortinglogging,但由于原始方法用于更改每个logging的顺序,所以在实际需要更改之后,这使我对性能感到头疼。 一个例子:

 Id Order 5 3 8 1 26 2 32 5 120 4 

现在我能做些什么来改变ID=26到3的logging的顺序?

我所做的是创build一个过程,检查目标订单(3)中是否有logging,如果没有,则更新行的订单(ID = 26)。 如果以目标顺序存在logging,则该过程执行自身发送具有target order + 1该行的ID作为参数。

这导致更新每一个logging后,我想改变一个空间:

 Id Order 5 4 8 1 26 3 32 6 120 5 

那么一个更聪明的人会做什么?

  • 我使用SQL Server 2008 R2。

编辑:

我需要一个项目的顺序列是足够的sorting没有涉及二级键。 单独的订单栏必须为其logging指定一个独特的地方。

除了所有这些,我不知道我是否可以实现像链接列表:“下一个”列而不是“订单”列以保留下一个项目ID。 但我不知道如何编写查询以正确的顺序检索logging。 如果有人也有这个方法的想法,请分享。

 Update product set order = order+1 where order >= @value changed 

虽然随着时间的推移,你会得到更大,更大的“空间”,但它仍然会“sorting”

这将在一个语句中将被改变的值和后面的每个值加1,但是上述语句仍然是正确的。 您的订单中可能会形成越来越大的“空间”,可能会超过INT值。

替代解决scheme给予无空格的愿望:

想象一个过程:UpdateSortOrder的参数是@NewOrderVal,@ IDToChange,@OrderOrderVal

两个步骤的过程取决于新/旧订单是否正在向上或向下移动。

 If @NewOrderVal < @OriginalOrderVal --Moving down chain --Create space for the movement; no point in changing the original Update product set order = order+1 where order BETWEEN @NewOrderVal and @OriginalOrderVal-1; end if If @NewOrderVal > @OriginalOrderVal --Moving up chain --Create space for the momvement; no point in changing the original Update product set order = order-1 where order between @OriginalOrderVal+1 and @NewOrderVal end if --Finally update the one we moved to correct value update product set order = @newOrderVal where ID=@IDToChange; 

关于最佳做法; 我所经常使用的大多数环境都希望按类别进行分组,并按字母顺序sorting或基于“销售热度”进行sorting,从而无需提供用户定义的sorting。

使用BASIC程序(以及其他地方)使用的旧技巧:将订单列中的数字跳转10或其他方便的增量。 然后,您可以在两个现有数字(即相距10)之间插入一行(实际上,最多9行,如果幸运的话)。 或者,您可以将第370行移到第565行,而不必更改570以上的任何行。

我曾经使用过的一个解决scheme,取得了一些成功,就是用“重量”而不是“秩序”。 重量是显而易见的,一个物品越重(即:数字越低)沉入底部,打火机(数量越高)越高。

如果我有多个重量相同的项目,我认为它们具有相同的重要性,我按字母顺序排列。

这意味着你的SQL看起来像这样:

 ORDER BY 'weight', 'itemName' 

希望有所帮助。

这是一个使用公共表格expression式(CTE)的替代方法。

此方法尊重SortOrder列上的唯一索引,并将closuressorting顺序中可能由早期的DELETE操作留下的任何空缺。

 /* For example, move Product with id = 26 into position 3 */ DECLARE @id int = 26 DECLARE @sortOrder int = 3 ;WITH Sorted AS ( SELECT Id, ROW_NUMBER() OVER (ORDER BY SortOrder) AS RowNumber FROM Product WHERE Id <> @id ) UPDATE p SET p.SortOrder = (CASE WHEN p.Id = @id THEN @sortOrder WHEN s.RowNumber >= @sortOrder THEN s.RowNumber + 1 ELSE s.RowNumber END) FROM Product p LEFT JOIN Sorted s ON p.Id = s.Id 

(对不起,我正在学习)

很简单 你需要有“基数孔”

结构你需要有2列

1)pk = 32bit int

2)order = 64bit bigint(BIGINT,NOT DOUBLE !!!)

插入/更新

1)当你插入第一个新logging时,你必须设置order = round(max_bigint / 2)。

2)如果你插入表的开始,你必须设置order = round(“第一个logging的顺序”/ 2)

3)如果你插入表的最后你必须设置order = round(“max_bigint – 最后一个logging的顺序”/ 2)

4)如果在中间插入,则必须设置order = round(“之前的logging顺序 – / 2之后的logging顺序)

这个方法有很大的意义。 如果你有约束错误,或者你认为你有小基数,你可以重build订单列(正常化)。

在规范化的最大情况下(有了这个结构)你可以在32位有“基数孔”。

简单而快速!

记得没有双重! 只有INT – 顺序是精确值!

我目前正在开发一个需要命令的树结构的数据库。 我使用一种链接列表方法,将在客户端(而不是数据库)上进行sorting。 sorting也可以通过recursion查询在数据库中完成,但这对于此项目来说不是必需的。

我做了这个文档,描述了如何实现sorting顺序的存储,包括postgresql中的一个例子。 请随意发表评论!

https://docs.google.com/document/d/14WuVyGk6ffYyrTzuypY38aIXZIs8H-HbA81st-syFFI/edit?usp=sharing