我有一个集中的对象一个数据库。图像在一个照片库,产品目录,各章中的一本书,等等。每个对象是表示作为一个行。我希望能够任意了这些图像存储,订购数据库中的所以我显示的对象,他们将在正确的顺序。

例如,我们说我是在写一本书,每一章节是一个对象。我写我的书,以及把各章节顺序如下:

介绍、可获取性、形式与功能、错误、一致性、结论,索引

它进入的编辑,并且回来了与下列建议的顺序:

介绍、形式、职能、可获得性、一致性、错误的结论,索引

我怎么可以储存这种排序的数据库,在一个强大、高效的方式?

我有以下想法,但是我不高兴他们中的任何:

  1. 阵列。每个排有序的ID,当顺序被改变(通过去除随后插入),以标识更新。这使得检索容易的,因为它只是 ORDER BY, 但它似乎很容易打破。

    // REMOVAL
    UPDATE ... SET orderingID=NULL WHERE orderingID=removedID
    UPDATE ... SET orderingID=orderingID-1 WHERE orderingID > removedID
    // INSERTION
    UPDATE ... SET orderingID=orderingID+1 WHERE orderingID > insertionID
    UPDATE ... SET orderID=insertionID WHERE ID=addedID

  2. 联清单。每个排有列为id的下一行中的顺序。遍历似乎代价高昂在这里,虽然有可能通过某种方式使用 ORDER BY 我不想的。

  3. 隔阵列。设置orderingID(如使用#1)要大,因此首先对象是100,第二是200等。然后当插入的事情发生了,你只是把它放在 (objectBefore + objectAfter)/2.当然,这将需要重新平衡偶尔,所以你没有的东西太靠近在一起的(即使是与浮,你会最终遇到四舍五入错误)。

没有这些似乎特别优雅的给我。没有任何人有一个更好的方式来做到这一点?

有帮助吗?

解决方案 9

因为我已经主要运行成本与Django,我已经找到了 这个解决方案 是最可行的。它似乎没有任何"权利的方式"这样做在一个关系数据库。

其他提示

其他替代办法将是(如果你的RDBMS支持)使用类型的列阵列。尽管这打破了正常化的规则,也可以是有用的,在情况是这样。一个数据库,这我知道这有阵列是PostgreSQL。

该acts_as_list混合在轨处理此基本上你的方式概述了#1.它看起来对于整数列所谓的位置(其中你可以复盖到名字的课程)和使用,做到一个订单。当你想要重新秩序的事情更新的职位。它曾我只是罚款,每次我使用它。

作为一个侧面说明,可以删除需要总是做重新定位插入/删除的使用稀疏编号--那种喜欢的基本回来的那天...你可以量你的职位的10,20,30,等等。如果你需要的东西插入中间10和20,你只是把它插入位置的15个。同样,当删除,你可以只删除该行和留下的空隙。你只需要做重新编号的时候你真的可以改变的顺序,或者如果你尝试做一个插入和没有适当的间隙,以插入。

当然这取决于特定情况(例如你是否有其他行已经载入存储器或不)它可以或不可以使用的间隙方法。

只是一个思考虑 选项1vs#3:没有隔开列的选择(#3)只有推迟的问题正常阵列(#1)?无论算法的选择,要么坏,你会遇到的问题与#3之后,或者它的作品,然后#1应该很好的工作。

如果在对象并不是严重键的其他表,并将名单很短,删除一切领域,只是重新插入的正确名单是最简单的。但是,这是不实际的,如果列出了很大,你有很多的限制,减慢删除。我认为你的第一个方法就是干净的。如果你在一个交易,你可以肯定没什么奇怪的事发生时你在中东的更新搞砸了订单。

我这样做在我的最后一个项目,但它是一个表,只是偶尔需要具体订的,并没有访问过于频繁。我认为间隔开列会是最好的选择,因为它重新排序将是最便宜的平均情况下,只涉及一个改变的一个值和查询在两个)。

此外,我想为了通过将相当严重优化通过数据库的供应商,所以利用这一功能将是有利的绩效而不是相联系清单的实施。

使用浮点数表示的每个位置的项目:

项目1->0.0

项目2->1.0

项目3->2.0

项目4->3.0

你可以把任何项目之间的任何其他两个项目通过简单的二分:

项目1->0.0

项目4->0.5

项目2->1.0

项目3->2.0

(移到项目4之间的项目1和2)。

二等分过程的可能继续几乎无限期地由于浮点数编码的计算机系统。

项目4->0.5

项目1->0.75

项目2->1.0

项目3->2.0

(移项目1的位置后,项目4)

我愿意做一个连续的数字,与一个触发表的"使得房间"一优先权,如果它已经存在。

我有这个问题。我是在沉重时间的压力(我们是不是所有)和我去选择#1,只有更新的行改变。

如果你换项目1和项目10,只是做两次更新更新了数项目1和项目10.我知道这是简单的算法,这是O(n)最糟糕的情况,但是,最糟糕的情况是,当你有一个总的排列的清单。如何经常的是事情发生?这就是你的答案。

我有同样的问题和可能已经花了至少一个星期关于自己有关的适当数据模型,但是我想我终于得到了它。使用的阵列数据类型在PostgreSQL,你可以储存的初级关键的每个订购项目和更新,列相应地使用插入或删除当你的订单的变化。引用一个单一的排将允许你把你所有的对象的基础上订购的阵列。

它仍然是一位波涛汹涌的一个解决方案,但它将可能更好地工作,比选择#1,因为备选方案1要求在更新了数的所有其他行时订购的变化。

方案1和方案#3具有相同的复杂性在每一个操作除外 INSERT 写。方案#1O(n)写上 INSERT 和方案#3O(1)写上 INSERT.

对于每一个其他数据库操作的复杂性是一样的。

方案#2甚至不应该被认为是因为它的 DELETE 需要O(n)读和写。方案1和方案#3O(1) DELETE 读和写。

新方法

如果你的要素有一个明显的父元(即他们共用一个外国的关键行),然后你可以尝试下...

Django提供一个数据库不可知的解决方案来存储整数列表内 CharField().一个缺点是,最大的长度存串不可能大于 max_length, ,这是DB依赖性。

在条款的复杂性,这将使方案#1O(1)写道 INSERT, 因为订购的信息将被储存作为一个单一的领域中的父元。

另一个缺点是 JOIN 对父母的行为现在需要更新排序。

https://docs.djangoproject.com/en/dev/ref/validators/#django.core.validators.validate_comma_separated_integer_list

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top