Создание узла – самое простое действие над деревом. Для того, что бы его осуществить нам потребуется уровень и правый ключ родительского узла (узел в который добавляется новый), либо максимальный правый ключ, если у нового узла не будет родительского.
Пусть [right_key] – правый ключ родительского узла, или максимальный правый ключ плюс единица (если родительского узла нет, то узел с максимальным правым ключом не будет обновляться, соответственно, чтобы не было повторов, берем число на единицу большее). [level] – уровень родительского узла, либо 0, если родительского нет.
Обновляем ключи существующего дерева, узлы стоящие за родительским узлом (1):
Но мы обновили только те узлы в которых изменяются оба ключа, при этом родительскую ветку (не узел, а все родительские узлы) мы не трогали, так как в них изменяется только правый ключ. Следует иметь в виду, что если у нас не будет родительского узла, то есть новый узел будет корневым, то данное обновление проводить нельзя.
Обновляем родительскую ветку (2):
Теперь добавляем новый узел (3):
Теперь можно объединить первые два запроса в один (4), что бы не делать лишних действий.
Удаление узла не намного сложнее, но требуется учесть, что у удаляемого узла могут быть подчиненные узлы. Для осуществления этого действия нам потребуется левый и правый ключ удаляемого узла.
Пусть [left_key] – левый ключ удаляемого узла, а [right_key] – правый
Удаляем узел (ветку) (5):
Обновляем ключи оставшихся веток:
Как и в случае с добавлением обновление происходит двумя командами: обновление ключей родительской ветки и обновление ключей узлов, стоящих за родительской веткой. Следует правда учесть, что обновление будет производиться в другом порядке, так как ключи у нас уменьшаются.
Обновление родительской ветки (6):
* Так как мы не знаем точное количество подчиненных узлов, мы вычисляем длину диапазона (смещения) ключей удаляемой ветки (узла).
Обновление последующих узлов (7):
Теперь можно объединить последние два запроса в один, что бы не делать лишних действий (8).
Перемещение узла – самое сложное действие в управлении деревом. На схеме показаны области, на которые можно разделить наше дерево. Из её можно увидеть, что узел может перемещаться только в две разные области: вышестоящих и нижестоящих узлов. Вообще, чем примечательно использование Nested Sets, что с помощью двух ключей ветки возможен выбор узлов любой области.

1. Вверх по дереву (в область вышестоящих узлов), включает в себя:
2. Вниз по дереву (в область нижестоящих узлов), включает в себя.
Для начала выберем ключи следующих узлов:
1. Ключи и уровень перемещаемого узла;
Получаем [level], [left_key], [right_key]
2. Уровень нового родительского узла (если узел перемещается в "корень" то сразу можно подставить значение 0):
Получаем [level_up]
3. Правый ключ узла за который мы вставляем узел (ветку):
Данный параметр, а не ключи нового родительского узла, выбираем по одной простой причине: Для обычного перемещения этого ключа нам будет достаточно, а при изменении порядка узлов и переноса в "корень" дерева данный параметр нам просто необходим.
Данная переменная берется в зависимости от действия:
**** Следует обратить внимание, что при поднятии узла вверх по порядку, узел выбирается не соседний, а следующий, за неимением оного (перемещаемый узел будет первым) берется левый ключ родительского узла
Получаем [right_key_near] и [left_key_near] (для варианта изменения порядка)
4. Определяем смещения:
Выбираем все узлы перемещаемой ветки:
Получаем [id_edit] - список id номеров перемещаемой ветки.
Так же требуется определить: в какую область перемещается узел, для этого сравниваем [right_key] и [right_key_near], если [right_key_near] больше, то узел перемещается в облась вышестоящих узлов, иначе - нижестоящих (почему существует разделение описано ниже).
Где у нас изменяются ключи по дереву во время переноса узла показано на схеме:

Как видно из схемы правые ключи меняются только у левой родительской ветки, левые ключи меняются у правой родительской ветки а оба ключа меняются в узлах находящихся между родительской старой и родительской новой веткой, области изменений, не меняются в зависимости от того, в какую (вышестоящую или нижестоящую) область перемещается узел. Отличием является, то что при перемещении в вышестоящую область ключи увеличиваются, а при переходе в нижестоящую - уменьшаются.
Хочу обратить внимание на то что у нас есть разница изменения ключей дерева в зависимости от того, в какую область перемещается узел (увеличение <-> уменьшение), а так же то, что правая родительская ветка может быть как старой, так и новой родительской веткой, то же самое и с левой родительской веткой. Поэтому порядок обновления ключей и условия выбора диапазонов областей различны, в зависимости от вида перемещения (вверх или вниз).
Возможно обновление ключей в три этапа: каждая ветка отдельно и диапазон между ними. Но так как мы меняем только два ключа, причем изменение на одно и то же число, то можно обойтись и двумя командами (UPDATE).
При перемещении вверх по дереву выделяем следующие области:


Хотел бы обратить внимание на то, что в условии с [right_key_near] и [left_key] дерево разделяется на разные области так как эти переменные сравниваются с разными ключами.
Определяем смещение ключей редактируемого узла [skew_edit] = [right_key_near] - [left_key] + 1.
Так как при в условиях не участвуют ключи кроме изменяемых, то порядок действий не имеет значения.
Теперь можно переместить ветку:
После оптимизации этих запросов получаем всего один:
В данной команде особое внимание нужно уделить порядку изменения полей таблицы, самым последним полем должно изменяться поле левого ключа (left_key), так как его значение является условием для изменения других полей.
Замечу, что при использовании этой команды, выбирать узлы перемещаемой ветки не нужно.
При перемещении вниз по дереву выделяем следующие области:


Опять же порядок не имеет значения, поэтому просто делаем команды на обновление. Правда хочу обратить внимание на тот факт, что в условии: "левый ключ узла меньше [right_key_near]" узел в котором находится [right_key_near] тоже попадает в диапазон изменения, следует иметь ввиду, что при сравнении не однотипных ключей (правый <-> левый) текущий узел попадает или не попадает в диапазон без использования равенства в условии.
Определяем смещение ключей редактируемого узла [skew_edit] = [right_key_near] - [left_key] + 1 - [skew_tree].
Теперь можно переместить ветку:
После оптимизации этих запросов получаем всего один:
Замечания те же, что и при перемещении ветки вверх по дереву.
На этом в общем-то все, в итоге получаем только четыре основных действия, основную сложность составляет подготовка переменных к перемещению узла.