我在mySql中有一个记录表。我需要维护用户指定的订单。所以我添加了一个“位置”列。
移动特定记录时更新所有记录的SQL语句是什么?我有类似的东西:
UPDATE items SET position = '2' WHERE id ='4';
UPDATE items SET position = position+1 WHERE position >= '2' AND id != '4';
但是,如果记录下降,那么大于将会更大。有什么诀窍?谢谢!
答案 0 :(得分:7)
这样的事情可以吗?
UPDATE items
SET position = CASE position
WHEN $oldpos THEN $newpos
ELSE position + SIGN($oldpos-$newpos)
END
WHERE position BETWEEN LEAST( $newpos, $oldpos )
AND GREATEST( $newpos, $oldpos );
我测试了几次,似乎有效。
答案 1 :(得分:2)
做这种事情,例如用户维护的行号的销售订单,我发现最好在BL或UI的数组中处理它。通常他们会想要调整几个记录,有时想说“忘记它”。所以最简单的可能是等到他们点击“确定”按钮(或你的等价物),然后用当前的顺序将它们全部写回来。
你也可能最终处理删除,这是另一个你可以用同样方法处理的问题。
答案 2 :(得分:1)
这是我对此的看法:我的row_index列的数字步长为10(例如:0,10,20,ecc。)。当用户更新其中一行时,您需要知道它是上升还是下降。如果必须将第2行移动到第4行(向下,所需的row_index = 30),则将row_index设置为35;否则(如果上升)将其设置为25.设置此值:
UPDATE your_table SET row_index = 35 WHERE your_id = 1234
现在你有正确的顺序,但是row_indexs搞砸了。要解决此问题,请执行以下两个查询:
SET @pos:=-10;
UPDATE your_table SET row_index = @pos:=@pos+10 WHERE ...
这将更新所有行(或使用where语句选择的行)并设置row_index列,不带间隙(0,10,20,30,ecc。)。当然这种方式会增加写操作的负担,但我认为这是在读操作期间获取订单的最快方法。如果删除一行,则可以重新运行修订订单查询。
答案 3 :(得分:0)
我建议,至少在项目之间使用大增量(比如10000)。然后只是做一个订单。如果你需要将11000移动到9000到10000之间,那么只需将其设置为9500并完成。
这并没有消除重新排序的问题,但它大大减少了它。在某些时候,你最好删除所有行,然后用正确的顺序读取它们。像你这样做的更新太容易出错了。
答案 4 :(得分:0)
您可以考虑使用链接列表类型的方法,使用下一个键,也可能是列表中的上一个项,然后您只需要更新一些记录,而不是所有记录。
答案 5 :(得分:0)
有趣!好的,所以没有简单的答案。我以为我只是遗漏了一些东西。我想过维护一个外部阵列。这听起来像是最好的主意。
答案 6 :(得分:0)
也许是这样的?
$item_id = $_GET['item_id'];
$position = $_GET['new_position'];
$old_position = $_GET['old_position'];
if($new_position < $old_position) {
SQL: UPDATE items SET position = position+1 WHERE position >= $new_position AND position < $old_position
} else {
SQL: UPDATE items SET position = position-1 WHERE position <= $new_position AND position > $old_position
}
SQL: UPDATE items SET position = $new_position WHERE item_id = $item_id