1

我的数据大致如下:

user_id   range   start   end
10        500     1       500
11        175
12        200

并需要将其转换为如下内容:

user_id   range   start   end
10        500     1       500
11        175     501     675
12        200     676     875

所以每个后续行的起始编号是前一行的结束编号。当前行的结束编号是开始编号 + range-1。

我试图纯粹在 SQL 中执行此操作,但似乎有点卡住,因为这会产生错误:

UPDATE  users U
SET     start = ( SELECT end+1 FROM users U2 WHERE U2.id = U.id - 1 )
WHERE   U.id > 1;

这导致You can't specify target table 'users' for update in FROM clause- 虽然我仍在寻找解决方案,但似乎无法找到解决方案。

4

2 回答 2

1

看看这个答案

基本上,用子查询更改您的子查询部分

(SELECT end+1 FROM (SELECT end, id FROM users) U2 WHERE U2.id = U.id - 1)

它很脏,但它应该可以工作。请注意,如果您的表很大(并且取决于 mysql 服务器上的其他一些配置值),它会非常慢,我不建议在生产代码中使用它。此外,您假设您拥有所有后续用户 ID,但情况可能并非如此。如果您的 id 上有空白,它将在该字段上设置为 null ,否则可能会失败。

如果您的 ID 上有空白,您可以执行以下操作:

(SELECT end+1 FROM (SELECT end, id FROM users) U2 WHERE U2.id < U.id LIMIT 1)
于 2012-09-14T16:04:03.407 回答
1

如果您有大型表,这将是一个缓慢的查询,但您可以使用交叉连接来解决这个问题。

UPDATE users U CROSS JOIN users U2
SET U.start = U2.end WHERE U.id = U2.id - 1;

我可能会考虑有一个附加字段的想法,该字段引用包含用于其起始值的结束值的记录。当您的自动增量存在差距时,这将允许有效的自加入更新并解决问题。查询可能看起来像

UPDATE users U INNER JOIN users U2 on U.prev_id = U2.id
SET U.start = U2.end;
于 2012-09-14T16:24:22.270 回答