更新排序索引列以移动项目

时间:2009-10-17 08:45:54

标签: mysql sql sql-update sql-order-by

如果我有下表&数据允许我们使用sort_index进行排序:

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上循环它们并不理想)
  2. 为了澄清我正在尝试做的事情,让我们假设该表是空的,所以我们有以下数据:

    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
    

    然后,如果我们要做以下的动作

    • Foo 1 to sort_index 3
    • Foo 7 to sort_index 1
    • Foo 5 to 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
    

1 个答案:

答案 0 :(得分:3)

您应该可以在一个查询中执行此操作:UPDATE foo SET sort_index = sort_index + 1 WHERE bar_id == b AND sort_index < s1 AND sort_index >= s2行,其中b是要移动的行的bar_id,{{1} }是该行的当前s1,而sort_index是您要将其移至的s2。然后,您只需更改行的sort_index

您可能希望在事务中执行两个查询。此外,如果您使用sort_index之类的内容在sort_index上创建索引,则可能会加快速度。

(顺便说一下,在这里我假设您不希望在给定的CREATE INDEX foo_index ON foo (sort_index)内重复sort_index个值,并且除了明确之外,不应更改行的相对顺序。你不需要这个,解决方案更简单。)