代码之家  ›  专栏  ›  技术社区  ›  DEfusion

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

  •  4
  • DEfusion  · 技术社区  · 15 年前

    如果我有下表和数据允许我们使用 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确定范围)
      • 确保 索尔特指数 始终为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
    

    如果我们要做下面的动作

    • foo 1排序索引3
    • foo 7排序索引1
    • foo 5排序索引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 回复  |  直到 6 年前
        1
  •  3
  •   David    15 年前

    您应该能够在一个查询中这样做:沿着 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 索尔特指数 你想把它移到。那么,你只要改变 索尔特指数 排成一行。

    您可能希望在事务内部执行这两个查询。此外,如果在 索尔特指数 使用类似 CREATE INDEX foo_index ON foo (sort_index) .

    (顺便说一下,我假设你不想要复制品 索尔特指数 给定值内的值 巴尔伊德 ,并且除非显式更改,否则不应更改行的相对顺序。如果您不需要这个,解决方案就更简单了。)