更改关系数据库中数据记录的顺序

时间:2010-11-23 16:17:29

标签: relational-database

假设我有1000多个或更多记录,我能想到改变记录顺序的唯一方法就是更新所有记录位置。

假设我有一个名为position的列,其中包含:

id   name      position
1    apples    1
2    oranges   2
3    pears     3
4    bananas   4
5    candy     5

假设用户想要在candyoranges之间移动pears。为此,我需要将candy的位置更新为3,然后使用position增加3-4条记录1。虽然可以使用单个查询完成,但仍需要锁定所有正在更新的记录,因此不是最佳记录。

还有另一种方法可以做到这一点,因为当你有很多记录时这似乎效率低下。我需要一种有效的方法来改变几个记录的位置,这些记录涉及尽可能少的表修改。

3 个答案:

答案 0 :(得分:1)

我从ext文件系统如何解决碎片问题中窃取了一个主意:

随机初始化您的位置字段,占用您数据类型所有可能值的范围。

每次您需要更改某些内容的位置时,只需在希望记录移动的范围内寻找一个空值,然后随机选择一个即可。

示例:

| id | pos    |
| 1  | 1002   |
| 2  | 15000  |
| 3  | 192185 |

现在,如果您想将3移到2之前和之后1,则只需选择一个随机位置pos,例如1002 < pos < 15000,这样您就可以将得到:

| id | pos    |
| 1  | 1002   |
| 3  | 9421   |
| 2  | 15000  |

从统计上讲,这将很好地起作用,直到大约80%个空间已满为止。有时您可能会得到零长度范围,在这种情况下,您将需要更改其他记录之一的位置,以便为新记录腾出空间。示例:

| id | pos    |
| 1  | 1002   |
| 2  | 1003   |
| 3  | 15000  |

同样,如果所需的新订单为1 > 3 > 2,则您首先需要为1找到一个新的地点,然后在它们之间放置3。假设是新的rand(0, 1002) == 42,那么您将得到类似的内容:

| id | pos    |
| 1  | 42     |
| 3  | 510    |
| 2  | 1003   |

在实现此算法时,请注意,进行空间操作可以递归进行,但是正如我所说,除非您有很多记录并且您的空间已达到80%以上,否则这是不太可能的。

答案 1 :(得分:0)

不是使用额外的字段来对数据进行排序,而是引入NextItem外键。您可以保留项目的原始主键。主键仍将作为标识值,但与排序顺序无关。

你可以拥有:

ID: 33, Name: The first item, NextItem: 48
ID: 48, Name: The second item, NextItem: 12
ID: 12, Name: The last item, NextItem: NULL

现在,您只需更改单个记录的'NextItem'即可完成重新排序数据。

答案 2 :(得分:-1)

合适的解决方案取决于您如何使用位置信息以及您的速度要求。如果您希望数据库在检索记录时执行位置排序(使用“ORDER BY位置”),我想不出一种方法可以避免更新受影响的每一行的位置信息。您可以通过将位置信息保存在单独的表中来略微减少过度杀伤,该表的行仅包含常规表PK的外键以及列“位置”。这样,您的数据库只需要在更小的表上进行更新。