【问题标题】:Update a sorting index column to move items更新排序索引列以移动项目
【发布时间】:2009-10-17 08:45:53
【问题描述】:

如果我有下表和数据允许我们使用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
    • 它应该完全在查询中完成,并且尽可能少(因为集合可能非常大,并且在它们上循环执行单独的 UPDATEs 并不理想)

为了澄清我想要做什么,我们假设表格是空的,所以我们有以下数据:

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

【问题讨论】:

  • 为了澄清您的问题:鉴于上面的插入,您希望在开头插入另一行 bar_id=1,从而导致所有后续行的更新(列 sort_index)@ 987654331@是1?
  • 总结您的要求,对于任何“bar_id”集,sort_index 必须从零开始并以 1 递增,直到最大的 sort_index 数。并且您想完全在 MySQL 中为任何移动/添加/删除操作执行此操作?

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


【解决方案1】:

您应该能够在单个查询中执行此操作:类似于UPDATE foo SET sort_index = sort_index + 1 WHERE bar_id == b AND sort_index < s1 AND sort_index >= s2,其中b 是要移动的行的bar_ids1 是当前的sort_index该行,s2 是您要将其移动到的sort_index。然后,您只需更改该行的sort_index

您可能希望在事务中执行这两个查询。此外,如果您使用 CREATE INDEX foo_index ON foo (sort_index) 之类的东西在 sort_index 上创建索引,它可能会加快速度。

(顺便说一下,这里我假设您不想在给定的bar_id 中重复sort_index 值,并且除非明确地更改行的相对顺序。如果您不这样做需要这个,解决方法就更简单了。)

【讨论】:

  • 这很时髦,几乎可以完美运行。但是,如果我想将一个项目移动到列表的末尾,它并不完全有效,因为我最终得到 2 具有相同的整理 sort_index 并且没有填充旧的 sort_index (例如,如果我将一个项目从 3 移动到 5 我最终得到 2,sort_index 为 5,没有 3)。
  • 实际上有一些情况(比如移动到列表的末尾)你需要使用它来代替: UPDATE foo SET sort_index = sort_index - 1 WHERE bar_id == b AND sort_index > s1 AND sort_index
  • 啊,是的,当然。事实上,不仅仅是当你将它移到列表的末尾,而是当你将它向前移动时。
猜你喜欢
  • 2012-07-02
  • 1970-01-01
  • 2016-08-05
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-02
  • 2011-01-01
相关资源
最近更新 更多