1

I have a table which references itself, like this:

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);

Sample data:

id   parent name
1    NULL   a
2    NULL   b
3    1      a1
4    1      a2
5    3      a1x
6    3      a2x

I want to write queries which will list the ancestors and decenders of a given row, e.g.

CALL find_ancestors('a1x')

Will return

id name
3  a1
1  a

and

CALL find_descendants('a')

Will return

id name
3  a1
5  a1x

How can I write these stored procedures for MySQL 5? Thanks


Bonus question for bounty: also select the distance of the returned row from the source and pass a maximum-distance parameter to the procedure, e.g.

CALL find_ancestors('a1x')

Will return

id name distance
3  a1   1
1  a    2

and

CALL find_ancestors_bounded('a1x',1)

Will return

id name distance
3  a1   1
4

1 回答 1

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 编写

于 2013-04-18T13:54:06.470 回答