SELECT
P2.emp,
SUM(S1.salary)
FROM
Personnel AS P1,
Personnel AS P2,
Salaries AS S1
WHERE
P1.lft BETWEEN P2.lft
AND P2.rgt
AND P1.emp = S1.emp
GROUP BY
P2.emp;
在邻接表模型中,你必须使用游标来完成这个功能。
找到每个节点的级别,以便你可以将树打印为缩进列表。
SELECT
COUNT(P2.emp) AS indentation,
P1.emp
FROM
Personnel AS P1,
Personnel AS P2
WHERE
P1.lft BETWEEN P2.lft
AND P2.rgt
GROUP BY
P1.emp
ORDER BY
P1.lft;
嵌套集模型具有邻接表模型没有的兄弟姐妹的隐含排序。插入一个新的节点作为最右边节点的兄弟节点。
BEGIN
DECLARE
right_most_sibling INTEGER;
SET right_most_sibling = (
SELECT
rgt
FROM
Personnel
WHERE
emp = :your_boss);
UPDATE
Personnel
SET
lft = CASE WHEN lft > right_most_sibling THEN
lft + 2
ELSE
lft
END,
rgt = CASE WHEN rgt >= right_most_sibling THEN
rgt + 2
ELSE
rgt
END
WHERE
rgt >= right_most_sibling;
INSERT INTO Personnel (emp, lft, rgt)
VALUES('New Guy', right_most_sibling, (right_most_sibling + 1))
END;
要将邻接表模型转换为嵌套集模型,请使用下推堆栈算法。假设我们有这些表:
树持有邻接表模型。
CREATE TABLE Tree
(emp CHAR(10) NOT NULL,
boss CHAR(10));
INSERT INTO Tree
SELECT emp, boss FROM Personnel;
-- Stack starts empty, will holds the nested set model
CREATE TABLE Stack
(stack_top INTEGER NOT NULL,
emp CHAR(10) NOT NULL,
lft INTEGER,
rgt INTEGER);
BEGIN
ATOMIC
DECLARE
counter INTEGER;
DECLARE
max_counter INTEGER;
DECLARE
current_top INTEGER;
SET counter = 2;
SET max_counter = 2 * (
SELECT
COUNT(*)
FROM
Tree);
SET current_top = 1;
INSERT INTO Stack
SELECT
1,
emp,
1,
NULL
FROM
Tree
WHERE
boss IS NULL;
DELETE FROM Tree
WHERE boss IS NULL;
WHILE counter <= (max_counter - 2)
LOOP
IF EXISTS (
SELECT
*
FROM
Stack AS S1,
Tree AS T1
WHERE
S1.emp = T1.boss
AND S1.stack_top = current_top) THEN
BEGIN
-- push when top has subordinates, set lft value
INSERT INTO Stack
SELECT
(current_top + 1), MIN(T1.emp), counter, NULL
FROM
Stack AS S1,
Tree AS T1
WHERE
S1.emp = T1.boss
AND S1.stack_top = current_top;
DELETE FROM Tree
WHERE emp = (
SELECT
emp
FROM
Stack
WHERE
stack_top = current_top + 1);
SET counter = counter + 1;
SET current_top = current_top + 1;
END
ELSE
BEGIN
-- pop the stack and set rgt value
UPDATE
Stack
SET
rgt = counter,
stack_top = - stack_top -- pops the stack
WHERE
stack_top = current_top
SET
counter = counter + 1;
SET current_top = current_top - 1;
END IF;
END LOOP;
END;