我需要将邻接列表转换为MySql中的嵌套集。我在互联网上只找到一个资源,使用mysql(http://data.bangtech.com/sql/nested_set_treeview.htm)将邻接列表转换为嵌套集。代码也在同一个网页上。
CREATE TABLE test.Tree
(emp CHAR(10) NOT NULL,
boss CHAR(10));
CREATE TABLE test.Personnel(
emp CHAR(20) PRIMARY KEY,
boss CHAR(20) REFERENCES Personnel(emp),
salary DECIMAL(6,2) NOT NULL
);
INSERT INTO test.Personnel VALUES ('jerry', 'NULL',1000.00);
INSERT INTO test.Personnel VALUES ('Bert', 'jerry',900.00);
INSERT INTO test.Personnel VALUES ('chuck', 'jerry',900.00);
INSERT INTO test.Personnel VALUES ('donna', 'chuck',800.00);
INSERT INTO test.Personnel VALUES ('eddie', 'chuck',700.00);
INSERT INTO test.Personnel VALUES ('fred', 'chuck',600.00);
INSERT INTO test.Tree
SELECT emp, boss FROM test.Personnel;
我从Personnel表中创建Tree表。树表具有老板 - 员工层次结构。这是一个邻接列表。为了将它转换为嵌套集,我应用了这段代码。
BEGIN ATOMIC
DECLARE counter integer;
DECLARE max_counter integer;
DECLARE current_top integer;
SET counter = 2;
SET max_counter = 2 * (SELECT COUNT(*) FROM test.Tree);
SET current_top = 1;
INSERT INTO test.Stack
SELECT 1, emp, 1, NULL
FROM test.Tree
WHERE boss IS NULL;
DELETE FROM test.Tree
WHERE boss IS NULL;
WHILE counter <=(max_counter - 2)
LOOP IF EXISTS (SELECT * FROM test.Stack AS S1, test.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 test.Stack
SELECT (current_top + 1), MIN(T1.emp), counter, NULL
FROM test.Stack AS S1, test.Tree AS T1
WHERE S1.emp = T1.boss
AND S1.stack_top = current_top;
DELETE FROM test.Tree
WHERE emp = (SELECT emp
FROM test.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 test.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;
MySQL工作台显示了一些我无法删除的语法错误。
我只熟悉mysql的非常基本的操作,所以无法自己调试代码。如何删除所有这些错误? Plz帮助。 我发现执行上述操作的第二个来源是http://www.sqlservercentral.com/articles/Hierarchy/94040/,但代码是在T Sql中,我没有足够的技能将其转换为MySQL。
答案 0 :(得分:0)
你应该在行
中放置NULL而不是'NULL'INSERT INTO test.Personnel VALUES('jerry','NULL',1000.00);
正确版本:
INSERT INTO test.Personnel VALUES('jerry',NULL,1000.00);
答案 1 :(得分:0)
使用Bash:
Bash转换:
# SQL command to fetch necessary fields, output it to text archive "tree"
SELECT id, parent_id, name FROM projects;
# Make a list "id|parentid|name" and sort by name
cat tree |
cut -d "|" -f 2-4 |
sed 's/^ *//;s/ *| */|/g' |
sort -t "|" -k 3,3 > list
# Creates the parenthood chain on second field
while IFS="|" read i p o
do
l=$p
while [[ "$p" != "NULL" ]]
do
p=$(grep -w "^$p" list | cut -d "|" -f 2)
l="$l,$p"
done
echo "$i|$l|$o"
done < list > listpar
# Creates left and right on 4th and 5th fields for interaction 0
let left=0
while IFS="|" read i l o
do
let dif=$(grep "\b$i,NULL|" listpar | wc -l)*2+1
let right=++left+dif
echo "$i|$l|$o|$left|$right"
let left=right
done <<< "$(grep "|NULL|" listpar)" > i0
# The same for following interactions
n=0
while [ -s i$n ]
do
while IFS="|" read i l nil left nil
do
grep "|$i,$l|" listpar |
while IFS="|" read i l o
do
let dif=$(grep "\b$i,$l|" listpar | wc -l)*2+1
let right=++left+dif
echo "$i|$l|$o|$left|$right"
let left=right
done
done < i$n > i$((++n))
done
# Show concatenated
cat i*|sort -t"|" -k 4n
# SQL commands
while IFS="|" read id nil nil left right
do
echo "UPDATE projects SET lft=$left, rgt=$right WHERE id=$id;"
done <<< "$(cat i*)"