| Oracle FAQ | Your Portal to the Oracle Knowledge Grid | |
Home -> Community -> Usenet -> comp.databases.theory -> Re: Nested set model with large gaps and spreads in the numbering
"--CELKO--" <71062.1056_at_compuserve.com> wrote in message
news:c0d87ec0.0209170539.7ce7653a_at_posting.google.com...
> >> For some reason, what you are trying to do reminds me of the > process of > defragmenting a disk. << > > Good thought! > > Richard Romley sent me a recursive UDF that computes the new left > value for a node. It can be put into one statement then used in > UPDATE Tree > SET lft = ShiftLeft(left), > rgt = ShiftLeft(left) + (rgt-lft); > > Very neat. I have to go out of town, but I will post it when I get > back.
Actually, it's possible to write a single view, with a few supporting views for clarity, that can calculate the total amount every node in the tree needs to be shifted, relative to some reference node, to move all gaps rightward. The algorithm is as follows:
forall(Paths P with head node H and tail node T where H = T or T is a
descendant of H, have T be the node whose shift amount will be
calculated with respect to the reference node H)
begin
Level(N) <= tailNodeLevel and
PN is the node at Level(N) within Path P and
N's lft value is <= PN's lft value)
begin
The translation of this to SQL is
With the helping views defined as
The procedure to actually shift the tree is now very straightforward and succinct
CREATE PROCEDURE ShiftLeftHelper
@node VARCHAR(10) -- reference node of tree or subtree to begin shifting
AS
BEGIN
UPDATE Tree
SET lft = Tree.lft - (SELECT gap
FROM ShiftedLeftValues
WHERE rootNode = @node AND
shiftNode = Tree.value),
rgt = Tree.rgt - (SELECT gap
FROM ShiftedLeftValues
WHERE rootNode = @node AND
shiftNode = Tree.value)
WHERE (SELECT gap
FROM ShiftedLeftValues
WHERE rootNode = @node AND
shiftNode = Tree.value) > 0
END -- PROCEDURE
This will produce the same results as my other algorithm. It would be interesting to evaluate the performance of these two approaches, especially on large trees.
Let's look at a couple of examples.
CREATE TABLE Tree
(
value VARCHAR(10) NOT NULL PRIMARY KEY,
lft INT NOT NULL CHECK (lft > 0),
rgt INT NOT NULL CHECK (rgt > 0),
CHECK (rgt > lft)
)
INSERT INTO TREE
SELECT 'Albert', 100, 1200
UNION ALL
SELECT 'Bert', 111, 201
UNION ALL
SELECT 'Ernie', 250, 300
UNION ALL
SELECT 'Chuck', 400, 1100
UNION ALL
SELECT 'Donna', 501, 601
UNION ALL
SELECT 'Eddie', 701, 801
UNION ALL
SELECT 'Fred', 901, 1001
To shift the entire tree
EXEC ShiftLeft
Tree becomes
value lft rgt
Albert 100 1200
Bert 101 191
Ernie 192 242
Chuck 243 943
Donna 244 344
Eddie 345 445
Fred 446 546
and to shift a subtree, for example,
EXEC ShiftLeftSubtree 'Chuck'
Tree becomes
Albert 100 1200
Bert 111 201
Ernie 250 300
Chuck 301 1001
Donna 302 402
Eddie 403 503
Fred 504 604
Regards,
jag
Received on Wed Sep 18 2002 - 16:19:14 CDT
![]() |
![]() |