我面临一个反复出现的问题我必须让用户重新排序存储在数据库中的列表。
我能想到的第一个简单的方法是有一个“position”列,其顺序保存为整数体育课
Data, Order
A 1
B 2
C 3
D 4
这里的问题是,如果我必须将foo插入位置2,那么现在我的表变成
Data, Order
A 1
FOO 2
B 3
C 4
D 5
所以要插入一个新行,我必须对一个包含五个元素的表执行一次创建和三次更新。
所以我的新想法是用实数代替整数,我的新表变成
Data, Order
A 1.0
B 2.0
C 3.0
D 4.0
如果我想在a之后插入元素foo,则
Data, Order
A 1.0
FOO 1.5
B 2.0
C 3.0
D 4.0
只执行一个SQL查询。
对于理论实数来说,这样做很好,但是浮点数的精度有限,我想知道这有多可行,我是否以及如何优化它,以避免在合理的修改次数下超过双精度
编辑:
这就是我现在在python中实现它的方式
@classmethod
def get_middle_priority(cls, p, n):
p = Decimal(str(p))
n = Decimal(str(n))
m = p + ((n - p)/2)
i = 0
while True:
m1 = round(m, i)
if m1 > p and m1 < n:
return m1
else:
i += 1
@classmethod
def create(cls, data, user):
prev = data.get('prev')
if prev is None or len(prev)<1:
first = cls.list().first()
if first is None:
priority = 1.0
else:
priority = first.priority - 1.0
else:
prev = cls.list().filter(Rotator.codice==prev).first()
next = cls.list().filter(Rotator.priority>prev.priority).first()
if next is None:
priority = prev.priority + 1.0
else:
priority = cls.get_middle_priority(prev.priority, next.priority)
r = cls(data.get('codice'),
priority)
DBSession.add(r)
return r
最佳答案
如果你想控制位置,而没有按顺序求解,那么一个相当简单和稳健的方法是指向下一个或前一个更新/插入/删除(第一个和最后一个除外)将需要3个操作。
Insert the new Item
Update the Item Prior the New Item
Update the Item After the New Item
建立之后,您可以使用CTE(带UNION ALL)创建一个永远没有限制的排序列表。
我已经看到了相当大的实现,这些实现是通过触发器来保持列表的完美形式完成的。不过,我不是触发器的粉丝,我只是把整个操作的逻辑放在一个存储过程中。