我有一个引用自己的表,如下所示:
CREATE TABLE Foo (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
parent INT NULL,
name VARCHAR (30) NOT NULL,
FOREIGN KEY (parent) REFERENCES Foo(id) ON DELETE CASCADE);
示例数据:
id parent name
1 NULL a
2 NULL b
3 1 a1
4 1 a2
5 3 a1x
6 3 a2x
我想编写将列出给定行的祖先和下行的查询,例如
CALL find_ancestors('a1x')
将返回
id name
3 a1
1 a
和
CALL find_descendants('a')
将返回
id name
3 a1
5 a1x
如何为MySQL 5编写这些存储过程?感谢
赏金的加值问题:还会选择返回行与来源的距离,并将最大距离参数传递给过程,例如
CALL find_ancestors('a1x')
将返回
id name distance
3 a1 1
1 a 2
和
CALL find_ancestors_bounded('a1x',1)
将返回
id name distance
3 a1 1
答案 0 :(得分:1)
假设我们有一个包含四个元素的表,id,item,class和parent_id。我们希望拥有任何给定项目的完整祖先,我们需要做的是一个自定义的mysql函数,它会实际循环遍历每个记录,寻找匹配我们的项目parent_id,一旦找到匹配项,如果匹配的项目有parent_id,它将再次开始循环,依此类推。每次我们的函数找到匹配项时,它都会将它存储在一个逗号分隔的字符串中,该字符串将在最后返回(例如:1,2,3,4)
我们的功能看起来像这样:
DELIMITER $$
DROP FUNCTION IF EXISTS `junk`.`GetAncestry` $$
CREATE FUNCTION `junk`.`GetAncestry` (GivenID INT) RETURNS VARCHAR(1024)
DETERMINISTIC
BEGIN
DECLARE rv VARCHAR(1024);
DECLARE cm CHAR(1);
DECLARE ch INT;
SET rv = '';
SET cm = '';
SET ch = GivenID;
WHILE ch > 0 DO
SELECT IFNULL(parent_id,-1) INTO ch FROM
(SELECT parent_id FROM pctable WHERE id = ch) A;
IF ch > 0 THEN
SET rv = CONCAT(rv,cm,ch);
SET cm = ',';
END IF;
END WHILE;
RETURN rv;
END $$
DELIMITER ;
此代码由RolandoMySQLDBA撰写