我有一个带有'Order'字段的MySql表但是当记录被删除时会出现一个间隙 如何按顺序更新“订单”字段? 如果可能,在一个查询1 1
id.........order
1...........1
5...........2
4...........4
3...........6
5...........8
到
id.........order
1...........1
5...........2
4...........3
3...........4
5...........5
我可以通过记录来做这个记录
按订单顺序获取SELECT,并逐行更改Order字段 但说实话,我不喜欢它。
谢谢
额外信息:
我也想以这种方式改变它:
id.........order
1...........1
5...........2
4...........3
3...........3.5
5...........4
到
id.........order
1...........1
5...........2
4...........3
3...........4
5...........5
答案 0 :(得分:4)
在MySQL中你可以这样做:
update t join
(select t.*, (@rn := @rn + 1) as rn
from t cross join
(select @rn := 0) const
order by t.`order`
) torder
on t.id = torder.id
set `order` = torder.rn;
在大多数数据库中,您也可以使用相关子查询执行此操作。但这可能是MySQL中的问题,因为它不允许将表更新为子查询:
update t
set `order` = (select count(*)
from t t2
where t2.`order` < t.`order` or
(t2.`order` = t.`order` and t2.id <= t.id)
);
答案 1 :(得分:0)
无需重新编号或重新订购。该表只是为您提供所有数据。如果您需要它以某种方式呈现,那就是查询的工作。
您甚至不需要更改查询中的订单值,只需执行以下操作:
SELECT * FROM MyTable WHERE mycolumn = 'MyCondition' ORDER BY order;
答案 2 :(得分:0)
上面的答案非常好,但我花了一段时间来理解它,所以我提供了一个轻微的重写,我希望能更快地让其他人清楚:
update
originalTable
join (select originalTable.ID,
(@newValue := @newValue + 10) as newValue
from originalTable
cross join (select @newValue := 0) newTable
order by originalTable.Sequence)
originalTable_reordered
on originalTable.ID = originalTable_reordered.ID
set originalTable.Sequence = originalTable_reordered.newValue;
请注意,originalTable。*不是必需的 - 只有用于最终连接的字段。
我的例子假设要更新的字段称为Sequence(意图可能比订单更清晰,但主要是回避保留的关键字问题)
我花了一段时间才得到原始答案中的“const”不是MySQL关键字。 (由于这个原因,我从来不是缩写的粉丝 - 有时可以通过多种方式解释,特别是在最好的时候,它们最好不要被误解。使用冗长的代码我知道,但清晰度总是胜过我书中的便利性。 )
不太确定选择@newValue:= 0是什么,但我认为这是在以后可以使用它之前必须表达变量的副作用。
此更新的值当然是对所有相关行的原子更新,而不是实际数据拉取和逐行更新单行。
我的下一个问题,这应该不难确定,但我已经了解到SQL在最好的时候可以成为一种技巧,就是看看这是否可以在数据子集上安全地完成。 (其中某些originalTable.parentID是一个设定值)。