Есть дерево Nested Set
Что бы переместить один узел на одну позицию выше (ниже) на том же уровне приходится делать несколько лишних манипуляций, а точнее:
1. Выбираем узел который перемещаем:
SELECT left_key, right_key, level FROM table WHERE id = $id
получаем: $left_key, $right_key и $level
2. Выбираем узел который выше по порядку (ниже - запрос аналогичен):
SELECT left_key, right_key FROM table WHERE right_key = $left_key - 1 AND level = $level
получаем: $left_key_up и $right_key_up
Получаем смещения ключей каждого узла:
$skew1 = $right_key - $left_key + 1
$skew2 = $right_key_up - $left_key_up + 1
Теперь, казалось бы, что можно просто в первой ветке уменьшить значения ключей на смещение ключей второй ветки, а во второй увеличить ключи на смещение ключей первой, но данная операция производится в два запроса и во время второго запроса меняются записи которые были уже изменены в первом. Поэтому приходится предварительно выбирать все идентификаторы подчиненных узлов перемещаемого узла, и делать изменения не относительно ключей а относительно идентификаторов:
3. Выбираем идентификаторы:
SELECT id FROM table WHERE left_key >= $left_key AND right_key <= $right_key
получаем: $id_move
4. Меняем ключи второго узла:
UPDATE table SET left_key = left_key - $skew1, right_key = right_key - $skew1 WHERE left_key >= $left_key_up AND right_key <= $right_key_up
5. Меняем ключи перемещаемого узла:
UPDATE table SET left_key = left_key + $skew2, right_key = right_key + $skew2 WHERE id IN ($id_move)
Возможно ли упростить данную операцию?