【发布时间】:2019-02-28 17:24:09
【问题描述】:
顶部的人希望在我们的应用程序中可以自定义排序顺序。所以我有一个有效定义数据类型的表。存储排序顺序的最佳方式是什么。如果我刚刚创建了一个名为“Order”之类的新列,那么每次我更新一行的顺序时,我想我都必须更新每一行的顺序以确保后代。有更好的方法吗?
顶部的人希望在我们的应用程序中可以自定义排序顺序。所以我有一个有效定义数据类型的表。存储排序顺序的最佳方式是什么。如果我刚刚创建了一个名为“Order”之类的新列,那么每次我更新一行的顺序时,我想我都必须更新每一行的顺序以确保后代。有更好的方法吗?
到目前为止,没有一个答案涉及自定义排序顺序的真正问题,当两个不同的人希望相同的记录以不同的方式排序时,就会发生这种情况。
如果您需要自定义排序顺序,则需要一个相关表来存储它,而不是额外的字段。该表将具有用户 ID、数据的记录 ID 和记录的排序顺序。这样,对于相同的数据,Joe Smith 可以有一个订单,而 Sally Jones 可以有另一个。现在您遇到了将新记录添加到数据集中的问题。您是将它们放在排序顺序的开头还是结尾,或者您是否需要该人为它们设置顺序,然后才能将它们添加到集合中。这实际上是一个非常复杂的问题,通常不值得花费大量时间来实施,因为一旦该系统到位,几乎没有人使用过(我的意思是我真的想检查一百条记录并标记个人每个的顺序?)。现在它在保存所有记录的顺序方面变得复杂了(这当然需要在下次运行查询时进行更改,因为会有新记录。)这是一个非常痛苦的有限直到过程。
我在一个提案编写应用程序中这样做过一次,因为我们需要能够按照我们认为对客户印象最深刻的顺序对提案中的部分和任务进行排序。即便如此,我们也必须制定一个默认订单,这样他们只需要移动他们真正想首先展示的两三件东西,而不是订购 10,000 个单独的零件。
如果您可以让他们购买它,一个更好的选择是允许他们按列(desc 或 asc)对数据进行排序。通常可以设计用户界面,以便如果您单击列标题,它将按该列处理数据。这相对简单,可以满足大多数定制订购的需求。
您确实需要与管理层讨论此要求,并了解他们希望它如何工作的详细信息,我想要定制订购。这通常是人们认为他们想要但并没有真正使用的东西之一。
【讨论】:
基本算法可能如下所述。最初,排序字段因项目而异,相差 1000(您可以考虑另一个间隔)。 为简单起见,表中的项目处于有序状态。 顺便说一句,我创建了Yii2 component 来管理这些东西。如果你需要一个可排序的树sortable tree,这个。
id | sort
---+-----
1 | 1000
---+-----
2 | 2000
---+-----
3 | 3000
---+-----
假设我们要在 id 1 之后添加一个项目(id 4):
id | sort
---+-----
1 | 1000
---+-----
4 | 1500
---+-----
2 | 2000
---+-----
3 | 3000
---+-----
因此,为了计算 id 4 的排序值,我们取了之前项目的排序值,即 1000 和之后的项目 - 2000 并取平均值。如果你得到一个浮点数,只需将它四舍五入到最接近的整数。 如果您需要在列表的开头插入一个项目,那么您取(1000 和 0,即 500)的平均值。
现在,如果我们需要在 id 1 之后插入一个项目(id 5),我们也这样做:
id | sort
---+-----
1 | 1000
---+-----
5 | 1250
---+-----
4 | 1500
---+-----
2 | 2000
---+-----
3 | 3000
---+-----
稍后,您可能会遇到这种情况:
id | sort
---+-----
1 | 1000
---+-----
15 | 1001
---+-----
...
---+-----
5 | 1250
---+-----
...
---+-----
因此,如果您需要在 1 到 15 之间插入一个项目(id 16),首先您应该将所有项目的排序字段增加 1000,然后再增加 1:
id | sort
---+-----
1 | 1000
---+-----
15 | 2001
---+-----
...
---+-----
5 | 2250
---+-----
...
---+-----
现在您可以插入项目(id 16):
id | sort
---+-----
1 | 1000
---+-----
16 | 1501
---+-----
15 | 2001
---+-----
...
---+-----
5 | 2250
---+-----
...
---+-----
【讨论】:
您可以改用浮点数,只要您有足够的精度,您始终可以将移动记录的序数列设置为两侧记录之间的中点。
【讨论】:
使用 int 字段。当您更新一行的排序顺序时,您只需更新您正在更新的行上的字段以及该行旧位置和新位置之间的任何行。这意味着交换两行只涉及接触那两行。此外,对于您要更新的不是“活动”行的行,您只需要增加或减少该字段;查询很容易编写。
【讨论】:
通常,应用程序会将适当的 ORDER BY 子句添加到查询中。如果要排序的结果集相对较小,您可以在选择标准上设置键。即使结果很大,对选定的数据进行排序通常也比按索引按顺序检索要好。
如果要求有像 B A Z T Q M K 这样的订单,那么您将需要一个列来放置相关订单。每次添加行时都需要确定适当的值。但是,这对于相对静态的代码表很有效。
【讨论】: