我有一张这样的表:
categoryID categoryName
----------------------------
1 A
2 B
3 C
现在我希望用户能够根据他的意愿订购这些数据。我想记住他对未来的首选订单。所以我想我会在上面的表格中添加一列order
,并将其设为INT
和AUTO_INCREMENT
类型。所以现在我得到一张这样的表:
categoryID categoryName order
-------------------------------------
1 A 1
2 B 2
3 C 3
4 D 4
我的问题是 - 用户现在决定,将categoryName
与订单4(上例中的D)一起带到2(上例中的B以上),这样表格现在看起来像:
categoryID categoryName order
-------------------------------------
1 A 1
2 B 3
3 C 4
4 D 2
我的问题是 - 当重新排序发生时,我应该如何为order
列分配新值。有没有办法在不更新表中的所有行的情况下执行此操作?
我想到的一种方法是将列设为FLOAT
,如果我想在列之间输入1,2,则将其命令为1.5。在这种情况下,当我重新订购商品时,我一直在失去精确度。
编辑: 另一种是更新(m,n)之间的所有行,其中m,n分别是源和目标订单。但这意味着运行(m-n)单独的查询不是吗?
编辑2:
假设我采用FLOAT
方法,我想出了这个sql来计算需要在id = 2的项目之后插入的项目的订单值(例如)。
select ((
select `order` as nextHighestOrder
from `categories`
where `order` > (
select `order` as targetOrder
from `categories`
where `categoryID`=2)
limit 1) + (
select `order` as targetOrder
from `categories`
where `categoryID`=2)) / 2;
这给了我3.5
这就是我想要实现的目标。
有没有更好的方法来写这个?请注意select order as targetOrder from categories where categoryID=9
执行两次。
答案 0 :(得分:4)
如果更改的数量相当小,如果您知道所涉及项目的ID,则可以生成一个笨拙但相当有效的UPDATE语句:
UPDATE categories
JOIN (
SELECT 2 as categoryID, 3 as new_order
UNION ALL
SELECT 3 as categoryID, 4 as new_order
UNION ALL
SELECT 4 as categoryID, 2 as new_order) orders
USING (categoryId)
SET `order` = new_order;
或(我更喜欢):
UPDATE categories
SET `order` = ELT (FIND_IN_SET (categoryID, '2,3,4'),
3, 4, 2)
WHERE categoryID in (2,3,4);
<强> UPD 强>:
假设您知道类别(或其名称)的当前ID,旧位置和新位置,您可以使用以下查询在列表中移动类别(为了向上移动,您必须更改between
条件和new_rank
计算到rank+1
):
SET @id:=2, @cur_rank:=2, @new_rank:=4;
UPDATE t1
JOIN (
SELECT categoryID, (rank - 1) as new_rank
FROM t1
WHERE rank between @cur_rank + 1 AND @new_rank
UNION ALL
SELECT @id as categoryID, @new_rank as new_rank
) as r
USING (categoryID)
SET rank = new_rank;
答案 1 :(得分:0)
Float的想法听起来很难理解,只是不向用户显示这些数字 - )
每当用户向上或向下移动条目时,您都可以找出上方和下方的条目。只需获取他们的订单号并找到平均值 - 这是已移动的条目的新订单。
答案 2 :(得分:0)
您可以将顺序保持为整数,并对拖动源索引和目标索引之间的所有项重新编号,因为它们无法拖动那么远,尤其是只有20个奇数类别。 Mulit-item drags使这更加复杂。
浮动更容易,但每次移动你发现中间你可以很快耗尽精确度,我会写一个测试,检查它不会最终放弃工作如果你继续移动第3项第二个位置一遍又一遍。
示例:
1,2,3
Move 3rd to 2nd
1,1.5,2
Move 3rd to 2nd
1,1.25,1.5
Move 3rd to 2nd
1,1.125,1.25
在excel电子表格中执行此操作,您会发现该数字对于浮点数来说太小了,无法在大约30次迭代中处理。
答案 3 :(得分:0)
好的,这与@newtover建议的相同,但是这两个简单的查询可以被任何其他开发人员更容易理解,即使是没有经验的人。
假设我们有一个表t1:
id name position
-------------------------------------
1 A 1
2 B 2
3 C 3
4 D 4
5 -E- 5
6 F 6
让我们将id = 5的项目'E'移动到第二个位置:
1)增加项目'E'的旧位置和'E'的所需位置(位置2,3,4)之间所有项目的位置
UPDATE t1 SET position=position+1 WHERE position BETWEEN 2 AND 4
2)现在位置2没有项目,所以'E'可以占据它的位置
UPDATE t1 SET position=2 WHERE id=5
结果,按'位置'排序
id name position
-------------------------------------
1 A 1
5 -E- 2
2 B 3
3 C 4
4 D 5
6 F 6
只有2个简单的查询,没有子查询。
限制:列“位置”不能是唯一的。但也许有一些修改也应该有效。
尚未对大型数据集进行测试。