Поддержание / обновление порядка записи в MySQL - PullRequest
2 голосов
/ 27 января 2009

У меня есть таблица рекордов в mySql. Мне нужно поддерживать порядок для них, как указано пользователем. Поэтому я добавил столбец «позиция».

Каким будет оператор SQL для обновления всех записей при перемещении определенной записи? У меня есть что-то вроде:

UPDATE items SET position = '2' WHERE id ='4';
UPDATE items SET position = position+1 WHERE position >= '2' AND id != '4';

Но больше, чем будет, будет меньше, чем если запись переместилась вниз. В чем подвох? Спасибо!

Ответы [ 7 ]

7 голосов
/ 27 января 2009

Может ли что-то подобное сделать?

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 );

Я проверял это пару раз, и похоже, что оно работает.

2 голосов
/ 27 января 2009

Такого рода вещи, например, заказы на продажу с номерами строк, поддерживаемыми пользователем, я нашел, что лучше всего обрабатывать их в массиве в BL или UI. Обычно они хотят настроить несколько записей, а иногда хотят сказать «забудь об этом». Поэтому проще всего подождать, пока они нажмут кнопку «ОК» (или ваш эквивалент), а затем записать их все обратно с текущим порядком.

Вы также можете в конечном итоге иметь дело с удалениями, что является еще одной проблемой, которую вы можете решить таким же образом.

1 голос
/ 28 января 2011

Это мое мнение: мой столбец 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 и т. Д.). Конечно, этот способ увеличивает нагрузку на операции записи, но я думаю, что это самый быстрый способ получить порядок во время операций чтения. Если вы удалите строку, вы можете просто выполнить запросы на исправление порядка.

0 голосов
/ 25 ноября 2013

Может как то так?

$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 
0 голосов
/ 27 января 2009

Интересно! Хорошо, поэтому нет простого ответа. Я думал, что просто что-то упустил. Я думал о поддержании внешнего массива. Это звучит как лучшая идея.

0 голосов
/ 27 января 2009

Вы можете рассмотреть возможность использования подхода связанного типа списка с ключом к следующему и, возможно, предыдущим элементом в списке, тогда вам нужно будет обновить только несколько записей вместо всех.

0 голосов
/ 27 января 2009

Я бы предложил, как минимум, использовать большие приращения (скажем, 10000) между элементами. Тогда просто делаю заказ по. Если вам нужно переместить 11000 между 9000 и 10000, просто установите его на 9500 и сделайте.

Это не устраняет проблему переупорядочения, но значительно уменьшает ее. В какой-то момент вам лучше удалить все строки, чем читать их в правильном порядке. Выполнение обновлений, как вы делаете, слишком чревато ошибками. Imho.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...