Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 在自引用表中查找祖先/中心的SQL_Mysql_Sql_Mysql5 - Fatal编程技术网

Mysql 在自引用表中查找祖先/中心的SQL

Mysql 在自引用表中查找祖先/中心的SQL,mysql,sql,mysql5,Mysql,Sql,Mysql5,我有一个表引用了它自己,如下所示: 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); DELIMITER $$ DROP FUNCTION IF EXISTS `junk`.`GetAncestry` $$ CR

我有一个表引用了它自己,如下所示:

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);
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 ;
样本数据:

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')
CALL find_ancestors('a1x')
会回来的

id name
3  a1
1  a
id name
3  a1
5  a1x
id name distance
3  a1   1
1  a    2
id name distance
3  a1   1

会回来的

id name
3  a1
1  a
id name
3  a1
5  a1x
id name distance
3  a1   1
1  a    2
id name distance
3  a1   1
如何为MySQL 5编写这些存储过程?谢谢

悬赏奖励问题:还选择返回行与源的距离,并将最大距离参数传递给过程,例如

会回来的

id name
3  a1
1  a
id name
3  a1
5  a1x
id name distance
3  a1   1
1  a    2
id name distance
3  a1   1

会回来的

id name
3  a1
1  a
id name
3  a1
5  a1x
id name distance
3  a1   1
1  a    2
id name distance
3  a1   1

假设我们有一个包含四个元素的表,id、item、class和parent_id。我们想要得到任何给定项的完整祖先,我们需要做的是一个定制的mysql函数,它实际上会在每个记录中循环寻找与我们的项parent_id匹配的项,一旦找到匹配项,如果匹配项有parent_id,它将再次开始循环,以此类推。每次我们的函数找到匹配项时,它都会将其存储在一个逗号分隔的字符串中,该字符串将在末尾返回,例如:1,2,3,4

我们的函数如下所示:

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

这段代码是RolandmySqlDBA编写的,假设我们有一个包含四个元素的表,id、item、class和parent_id。我们想要拥有任何给定项的完整祖先,我们需要做的是一个自定义mysql函数,一旦找到匹配项,它将实际循环通过每个记录寻找与我们的item parent_id匹配的项,如果匹配项具有父项id,它将再次开始循环,以此类推。每次我们的函数找到匹配项时,它都会将其存储在一个逗号分隔的字符串中,该字符串将在末尾返回,例如:1,2,3,4

我们的函数如下所示:

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);
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编写的

我考虑过阅读Joe Celko在SQL for Smarties中的树和层次结构,它涵盖了这类问题。这是一个迷人的理论素材,但我一直想知道sql树,人们在实践中实际使用它们的目的是什么?在我的例子中,a是欧洲,b是亚洲,a1是奥地利,等等……啊。谢谢说读这本书作为我的答案是不够的,所以我不会把它作为答案。但上面塞尔科的书几乎就是圣经。关于它的另一种解释,请参见上面的例子,它似乎是在处理二叉树,或者至少链接的例子是这样的。而且,由于手头没有这本书,我很想给n元示例代码打分。虽然答案中给出的示例是一个二叉树,但我不认为该技术中有任何东西将其限制为二叉树。请注意,修改后的预排序树遍历技术几乎要求您的数据是固定的——对于大型动态树,您的数据库将通过不断地对树进行重新排序来进行处理。不过,通过存储过程的迭代解决方案可以让您保持结构不变。我曾考虑阅读Joe Celko在SQL for Smarties中的树和层次结构,其中涵盖了此类问题。这是一个迷人的理论素材,但我一直想知道sql树,人们在实践中实际使用它们的目的是什么?在我的例子中,a是欧洲,b是亚洲,a1是奥地利,等等……啊。谢谢说读这本书作为我的答案是不够的,所以我不会把它作为答案。但上面塞尔科的书几乎就是圣经。关于它的另一种解释,请参见上面的例子,它似乎是在处理二叉树,或者至少链接的例子是这样的。而且,由于手头没有这本书,我很想给n元示例代码打分。虽然答案中给出的示例是一个二叉树,但我不认为该技术中有任何东西将其限制为二叉树。请注意,修改后的预排序树遍历技术几乎要求您的数据是固定的——对于大型动态树,您的数据库将通过不断地对树进行重新排序来进行处理。通过存储过程的迭代解决方案将允许您保持结构不变。