Пользовательские переменные на помощь, если вы еще не используете MySQL 8, который предоставляет оконные функции, такие как ROW_NUMBER ():
UPDATE t
JOIN (
SELECT
t.*
, @n := @n + 1 as n
FROM t
, (SELECT @n := 0) var_init
ORDER BY position
) sq ON t.id = sq.id
SET t.position = sq.n;
БОНУС:
Это становится немного сложнее, когда у вас несколько групп.
Например,для примеров данных, подобных этому
| id | position | fk |
|-----|----------|-----|
| 4 | 1 | 123 |
| 2 | 2 | 123 |
| 5 | 4 | 123 |
| 3 | 5 | 123 |
| 40 | 1 | 234 |
| 20 | 2 | 234 |
| 180 | 3 | 234 |
| 30 | 5 | 234 |
, запрос будет
UPDATE t
JOIN (
SELECT
t.*
, @n := if(@prev_fk != fk, 1, @n + 1) as n
, @prev_fk := fk
FROM t
, (SELECT @n := 0, @prev_fk := NULL) var_init
ORDER BY fk, position
) sq ON t.id = sq.id
SET t.position = sq.n;
Здесь вы просто сохраните текущий fk в другой переменной.При обработке следующей строки переменная по-прежнему содержит значение «предыдущей строки».Затем вы сбрасываете переменную @n
, когда значение изменяется.
- видит, как оно работает в реальном времени в sqlfiddle
UPDATE:
В MySQL 8 вы можете использовать оконную функцию row_number()
следующим образом:
update t join (
select t.*, row_number() over (partition by fk order by position) as new_pos
from t
) sq using (id) set t.position = sq.new_pos;