2009-10-17 87 views
4

如果我有以下表&数据允许我们使用sort_index排序:MySQL的更新排序索引列到移动项目

CREATE TABLE `foo` (
    `id` INT(11) NOT NULL AUTO_INCREMENT, 
    `bar_id` INT(11) DEFAULT NULL, 
    `sort_index` INT(11) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
); 

INSERT INTO `foo` (`bar_id`, `sort_index`) VALUES 
(1,1),(1,2),(1,3),(1,4), 
(2,1),(2,2),(2,3),(2,4),(2,5); 

我希望能够做到以下几点以最有效方式:

  1. 移动FOO条目到给定位置(由bar_id作用域)
    • 确保sort_index始终为1索引,有没有间隙
    • 您应该能够将项目移至开始和列表和规则#2仍应适用结束
    • 应在查询全部完成,尽可能少的可能(因为台可能是非常大的循环在他们做个别UPDATE s的不理想)

为了澄清什么,我试图做的,让我们假设该表是空的,所以我们有以下数据:

id | bar_id | sort_index 
1 | 1  | 1 
2 | 1  | 2 
3 | 1  | 3 
4 | 1  | 4  
5 | 2  | 1 
6 | 2  | 2 
7 | 2  | 3 
8 | 2  | 4 
9 | 2  | 5 

然后如果我们做以下动作

  • 富1至sort_index 3
  • FOO 7 sort_index 1个
  • 富5 sort_index 5

我们应得的以下数据:

id | bar_id | sort_index 
1 | 1  | 3 
2 | 1  | 1 
3 | 1  | 2 
4 | 1  | 4  
5 | 2  | 5 
6 | 2  | 2 
7 | 2  | 1 
8 | 2  | 3 
9 | 2  | 4 

SELECT * FROM foo ORDER BY bar_id, sort_index;给我们:

id | bar_id | sort_index 
2 | 1  | 1 
3 | 1  | 2 
1 | 1  | 3 
4 | 1  | 4 
7 | 2  | 1 
6 | 2  | 2 
8 | 2  | 3 
9 | 2  | 4 
5 | 2  | 5 
+0

为了澄清你的问题:给定上面的插入,你希望在开始时插入另一个'bar_id' = 1的行,导致所有后续行的更新(列'sort_index') 'bar_id'是1的位置? – tangens 2009-10-17 08:56:55

+0

总结您的要求,对于任何一组“bar_id”,sort_index必须从零开始,并加1,直到最大的sort_index数字。你想完全在MySQL中执行任何移动/添加/删除操作? – 2009-10-17 08:58:40

回答

3

你应该能够做到这一点的一个查询:沿UPDATE foo SET sort_index = sort_index + 1 WHERE bar_id == b AND sort_index < s1 AND sort_index >= s2,其中b是该行的bar_id要移动的东西线,s1是当前sort_index那一行,而s2是你想要移动到的sort_index。然后,您只需更改该行的sort_index

您可能想要在事务中执行两个查询。另外,如果您使用CREATE INDEX foo_index ON foo (sort_index)之类的东西在sort_index上创建索引,它可能会加快速度。 (顺便说一句,在这里我假设你不希望在给定的bar_id内重复sort_index值,并且行的相对顺序不应该被改变,除非明确的。如果你不需要这个,解决方法更简单:)

+0

这是相当时髦,几乎完美的作品。然而,如果我想将一个项目移动到列表的末尾,那么它不起作用,因为我最终得到的结果是2与sort_index相同并且没有填充旧的sort_index(例如,如果我将项目从3移动到5 I以sort_index为5结尾2​​,没有3)。 – DEfusion 2009-10-17 10:53:18

+1

实际上有一些情况(如移动到列表的末尾),你需要使用它来代替:UPDATE foo SET sort_index = sort_index - 1 WHERE bar_id == b AND sort_index> s1 AND sort_index <= s2 – DEfusion 2009-10-17 11:27:04

+0

啊是的,当然。事实上,这不仅仅是当你将它移动到列表的最后,它只是当你将它向前移动时。 – David 2009-10-17 11:55:44