| 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
71062.1056_at_compuserve.com (--CELKO--) wrote in
news:c0d87ec0.0210041151.6cfc30d8_at_posting.google.com:
>>> Writing a book AND moving! You're a glutton for punishment. :-) <<
>>> Looking over the many posts in this forum concerning the nested set
I've finally found a "simple" sql that calculates all the shifts in this model or also in the original nested set model. The only condition is that you can calculate the nr of "slots" that a row really occupies (I call it the gap).
In your case above that would be:
emp trv_nbr rgt_most gap
'Albert' 1 6 6 'Bert' 2 2 1 'Chuck' 3 6 4 'Donna' 4 4 1 'Eddie' 5 5 1 'Fred' 6 6 1
This is incidently milkchaser's num_descendants + 1. But only because you don't have any empty "slots".
To calculate the shift of every row, you take all the gaps of its siblings, the siblings of its parent, the siblings of its grandparent, ... which come before the row. That is the gap of all rows that come before the row and don't have an ancestor that is not an ancestor of this row. Then you add the number of ancestors, since each row needs 1 slot. Here only ancestors are relevant, since other rows have been dealt with by the gaps of their respective ancestor.
SELECT trv_nbr, rght_most,
(SELECT SUM(rght_most - trv_nbr + 1)
FROM Employees before
WHERE before.rght_most < emp.trv_nbr AND NOT EXISTS
(SELECT trv_nbr
FROM Employees parent
WHERE parent.trv_nbr < before.trv_nbr AND
before.trv_nbr <= par.rght_most AND
parent.rght_most < emp.trv_nbr)) AS gaps,
(SELECT COUNT(*)
FROM Employees parent
WHERE parent.trv_nbr < emp.trv_nbr AND
emp.trv_nbr <= parent.rght_most) AS parents,
COALESCE(gaps, 0) + parents + 1 AS shift
FROM Employees emp
I'm not sure whether you could directly plug this into an update according to the SQL standard, since I don't know whether all the values of shift have to calculated before the update is made.
But you can surely write a stored procedure that opens a cursor (as a snapshot) on the select above and adjust trv_nbr and rght_most for every row.
Regards,
Heinz
Received on Tue Oct 08 2002 - 00:48:20 CDT
![]() |
![]() |