如何将特定的,可变的“订单”保存到数据库中

时间:2009-01-31 12:56:42

标签: database sorting database-design

假设我有一些对象,我希望用户能够以他们希望的任何方式对它们进行重新排序,例如,通过拖动它们。所以我有

  • 干酪
  • 松饼

然后用户将“牛奶”拖到顶部,进行新订单

  • 干酪
  • 松饼

是否有最佳实践如何将这些对象的顺序存储在数据库中?天真的方法可能只是为每个对象存储一个名为“order”的数值,但这对我来说似乎太麻烦了,因为你必须在大多数时间内对顺序值进行洗牌。

9 个答案:

答案 0 :(得分:16)

我发现处理此问题的最佳方法是使用浮点顺序字段。当您在其他两个项目之间移动某些内容时,请将该字段设置为其邻居之间的中间位置。

读取和写入都很便宜。唯一的缺点是花车不断变长:)

答案 1 :(得分:12)

您建议的“天真”方法也是最佳做法!

答案 2 :(得分:12)

考虑到Tony Andrews的回答,您可以选择在每个条目中存储“下一个”索引。然后当你把它们全部拉进去时,按照链条走完阵列。这样可以更轻松地移动项目,因为您只需触摸最多两行。

这种方法的缺点是,如果您需要一个子集(例如前三项),您仍需要提取所有项目,或使用SQL循环。因此,在更新期间影响所有行或在读取期间访问所有项目之间。与以往一样,测量速度,看看哪种情况更适合您的情况。

答案 3 :(得分:5)

特别关注Tony Andrew和Mark的答案,似乎我真的只有两种选择:

  • 保存“下一个”值,使对象的行为类似于链接列表(请参阅Mark的回答)
    有了这个,改变订单很便宜,但我必须检索项目,然后按照“下一个”值排序,这很贵
  • 保存'订单'值(参见Tony Andrew的回答)
    这使得检索便宜但保存新订单可能很昂贵,因为在最坏的情况下,我必须更改所有订单值。 cletus指出,可以使用2 ^ n形式的大数字作为订单乘数。

Meta:所有这些答案都是正确的,我应该选择哪一个正确?

答案 4 :(得分:3)

在我的应用程序中,读取操作将比写入更频繁地发生。使用数值来指示排序顺序并处理重新排序项目的成本。这可以通过以下事实弥补:您可以按正确顺序有效地检索项目以用于显示目的(在典型应用程序中,这种情况发生的频率高于求助程序)。

此外,如前所述,如果您检索数据的子集(过滤类型或其他内容),其余项目仍处于正确的排序顺序。

记住口头禅K.I.S.S。

答案 5 :(得分:2)

如果您希望以相同的顺序重新显示它们并且您希望它们能够随时重新排序,我认为您无法在数据库中存储一些表示显示优先级的值。我使用了您描述的方法在FAQ中订购项目,与授权相关的研究人员,菜单中项目的顺序,......

答案 6 :(得分:2)

是的,在关系数据库中没有顺序,这是基本概念之一。所以没有数值或类似的东西就没有办法。

答案 7 :(得分:0)

您可以使用上一个ID,将您最后插入的行ID设置为上一个ID的每次新插入,

table, td {
  border: .2px solid black
}
<table>
  <tr>
    <td>ID</td>
    <td>NAME</td>
    <td>PREV_ID</td>
  </tr>
  <tr>
    <td>1</td>
    <td>first_item</td>
    <td><i>&lt;null&gt;</i></td>
  </tr>
  <tr>
    <td>2</td>
    <td>second_item</td>
    <td>1</td>
  </tr>
  <tr>
    <td>3</td>
    <td>thid_item</td>
    <td>2</td>
  </tr>
</table>

任何时候您只要重新排序即可轻松插入最后一行ID, 如果您在每个新插入内容中都使用下一个ID,则需要更新前一个ID, 如果在任何更新中使用排序顺序,则必须更新多行。 现在可以选择postgreSQL递归查询

答案 8 :(得分:0)

理论上,如果要获取某个特定元素的值,则可以使用Order Statistic Tree,或者通常使用某种 B树来存储该值。如果它们发生更改,则在最坏的情况下您将更改O(log n)个项目。如果您有30,000件商品,则只需更改4或5或5件即可保持订单。