Поддержание/обновление порядка записей в MySQL
-
20-08-2019 - |
Вопрос
У меня есть таблица записей в mySql.Мне нужно поддерживать для них порядок, указанный пользователем.Поэтому я добавил столбец «Позиция».
Каким будет оператор SQL для обновления всех записей при перемещении определенной записи?У меня есть что-то вроде:
UPDATE items SET position = '2' WHERE id ='4';
UPDATE items SET position = position+1 WHERE position >= '2' AND id != '4';
Но чем больше, тем меньше будет, чем если бы рекорд опустился вниз.В чем хитрость?Спасибо!
Решение
Выполнение подобных вещей, например.заказы на продажу с номерами строк, поддерживаемыми пользователем, я считаю, что лучше всего обрабатывать их в массиве в BL или пользовательском интерфейсе.Обычно они хотят исправить несколько записей, а иногда хотят сказать «забудь об этом».Поэтому проще всего просто подождать, пока они не нажмут кнопку «ОК» (или ее эквивалент), а затем записать их все обратно в текущем порядке.
В конечном итоге вы также можете столкнуться с удалением, и это еще одна проблема, с которой вы можете справиться таким же образом.
Другие советы
Поможет ли что-то подобное?
UPDATE items
SET position = CASE position
WHEN $oldpos THEN $newpos
ELSE position + SIGN($oldpos-$newpos)
END
WHERE position BETWEEN LEAST( $newpos, $oldpos )
AND GREATEST( $newpos, $oldpos );
Я проверил это пару раз, и это, кажется, работает.
Вот мой взгляд на это:мой столбец row_index имеет номер с шагом 10 (например:0, 10, 20 и т. д.).Когда пользователь обновляет одну из строк, вам нужно знать, увеличивается она или уменьшается.Если вам нужно переместить 2-ю строку на 4-ю (вниз, желаемый row_index = 30), вы устанавливаете row_index на 35;в противном случае (при повышении) установите значение 25.Установите это значение:
UPDATE your_table SET row_index = 35 WHERE your_id = 1234
Теперь у вас правильный порядок, но row_indexes перепутаны.Чтобы это исправить, выполните два запроса:
SET @pos:=-10;
UPDATE your_table SET row_index = @pos:=@pos+10 WHERE ...
Это обновит все ваши строки (или ту, которую вы выбираете с помощью оператораwhere) и установите столбец row_index без пробелов (0, 10, 20, 30 и т. д.).Конечно, такой способ добавляет нагрузку на операции записи, но я думаю, что это самый быстрый способ получить порядок во время операций чтения.Если вы удалите строку, вы можете просто повторно запустить запросы на фиксацию порядка.
Я бы предложил, как минимум, использовать большие приращения (скажем, 10 000) между элементами.Тогда просто делаю заказ.Если вам нужно переместить 11000 между 9000 и 10000, просто установите значение 9500 и готово.
Это не устраняет проблему переупорядочения, но значительно уменьшает ее.В какой-то момент вам лучше удалить все строки, а затем прочитать их в правильном порядке.Выполнение обновлений, как вы, слишком подвержено ошибкам, по моему мнению.
Вы можете рассмотреть возможность использования подхода типа связанного списка с ключом к следующему и, возможно, предыдущему элементу в списке, тогда вам нужно будет обновить только несколько записей, а не все из них.
Интересный!Ладно, простого ответа нет.Я думал, что просто что-то упускаю.Я думал о сохранении внешнего массива.Это звучит как лучшая идея.
Может быть, что-то вроде этого?
$item_id = $_GET['item_id'];
$position = $_GET['new_position'];
$old_position = $_GET['old_position'];
if($new_position < $old_position) {
SQL: UPDATE items SET position = position+1 WHERE position >= $new_position AND position < $old_position
} else {
SQL: UPDATE items SET position = position-1 WHERE position <= $new_position AND position > $old_position
}
SQL: UPDATE items SET position = $new_position WHERE item_id = $item_id