I\'d need a MySQL query that moves a node and all its children within a nested set. I found this site, but that function just seems so illogical - there\'s no universe
There are many answers already, but I feel like mine can be useful for someone. Based on answer of Roger Keays (thank you very much!), I wrote stored procedures for mySQL database:
-- to move target before specified node
CREATE DEFINER=`root`@`%` PROCEDURE `move_before`(IN target_id int, before_id int)
BEGIN
SELECT @new_pos := lft FROM dirs WHERE id = before_id;
CALL move(target_id, @new_pos);
END
-- to move target after specified node
CREATE DEFINER=`root`@`%` PROCEDURE `move_after`(IN target_id int, after_id int)
BEGIN
SELECT @new_pos := rgt + 1 FROM dirs WHERE id = after_id;
CALL move(target_id, @new_pos);
END
-- to move target to the specified node
CREATE DEFINER=`root`@`%` PROCEDURE `move_in`(IN target_id int, parent_id int)
BEGIN
SELECT @new_pos := rgt FROM dirs WHERE id = parent_id;
CALL move(target_id, @new_pos);
END
--main procedure to move target before position
CREATE DEFINER=`root`@`%` PROCEDURE `move`(in target_id int, in new_pos int)
BEGIN
SELECT @oldlft := lft, @oldrgt := rgt
FROM dirs
WHERE target_id = id;
SET @width := @oldrgt - @oldlft +1;
SET @distance := new_pos - @oldlft;
SET @tmppos := @oldlft;
IF (@distance <0)
THEN
SELECT @distance := @distance - @width;
SELECT @tmppos := @tmppos + @width;
END IF;
-- create new space for subtree
UPDATE dirs SET lft = lft + @width WHERE lft >= new_pos;
UPDATE dirs SET rgt = rgt + @width WHERE rgt >= new_pos;
-- move subtree into new space
UPDATE dirs SET lft = lft + @distance, rgt = rgt + @distance
WHERE lft >= @tmppos AND rgt < @tmppos + @width;
-- remove old space vacated by subtree
UPDATE dirs SET lft = lft - @width WHERE lft > @oldrgt;
UPDATE dirs SET rgt = rgt - @width WHERE rgt > @oldrgt;
END