Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/9.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查询中的递归?_Mysql_Loops_Recursion_Subquery - Fatal编程技术网

一个MySQL查询中的递归?

一个MySQL查询中的递归?,mysql,loops,recursion,subquery,Mysql,Loops,Recursion,Subquery,我已经建立了一个网络/树,现在,从一个节点开始,我尝试选择位于这一个节点和另一个节点之间的所有节点–全部在一个查询中 假设有两个表,一个用于存储具有属性的对象,另一个用于存储它们的(直接)关系。让我们保持示例的简单性 CREATE TABLE objects (id varchar(64) PRIMARY KEY); INSERT INTO objects VALUES ('seat'), ('chair'), ('furniture'), ('barstool'), ('stool'); C

我已经建立了一个网络/树,现在,从一个节点开始,我尝试选择位于这一个节点和另一个节点之间的所有节点–全部在一个查询中

假设有两个表,一个用于存储具有属性的对象,另一个用于存储它们的(直接)关系。让我们保持示例的简单性

CREATE TABLE objects (id varchar(64) PRIMARY KEY);
INSERT INTO objects VALUES ('seat'), ('chair'), ('furniture'), ('barstool'), ('stool');

CREATE TABLE parentships ( parent varchar(64) NOT NULL, child varchar(64) NOT NULL, PRIMARY KEY (parent, child), CONSTRAINT fk_child FOREIGN KEY (child) REFERENCES objects (id), CONSTRAINT fk_parent FOREIGN KEY (parent) REFERENCES objects (id) );
INSERT INTO parentships VALUES ('furniture', 'seat'), ('seat', 'chair'), ('seat', 'stool'), ('stool', 'barstool');
家具是根/端点节点。让我试着想象一下这个小网络/树

furniture --- seat -+- chair
                    |
                    +- stool --- barstool
我假设我需要使用
SUBSELECT
LOOP
和过程创建递归,但我以前从未使用过
LOOP
或自制过程。也许你可以帮我解释一下,而我会继续自己搜索/尝试

{magic query (parameter 'barstool')}

+-----------+
| parent    |
+-----------+   <--- This is what I want.
| stool     |
| chair     |
| seat      |
| furniture |
+-----------+
但是循环的文档让我很困惑。这是我的尝试,但我收到错误消息:

CREATE PROCEDURE find_all_ancestors(node varchar)
BEGIN
  SET @p = '';
  label1: LOOP
    SET @p = ( SELECT parent FROM parentships WHERE child IN (node, @p) );
    IF @p != 'furniture' THEN
      ITERATE label1
    END IF
    LEAVE label1
  END LOOP label1
  SET @x = @p
END
但我收到了几条错误消息,从这条开始:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'label1: LOOP
    SET @p = ( SELECT parent FROM parentships WHERE child ' at line 4
此外,我还需要将迭代的@p添加到中间结果数组中,MySQL不允许使用数组。所以也许我用的方法完全是错误的


干杯。

试试下面的版本-这是您的代码,只是稍微修改了一下。 执行后,它返回以逗号分隔的列表以及相应的值

我还在代码中添加了一些注释

DELIMITER // /* It enables the ; delimiter used in the procedure body to be passed through to the server rather than being interpreted by mysql itself*/

DROP PROCEDURE IF EXISTS find_all_ancestors // 

CREATE PROCEDURE find_all_ancestors(node varchar(100)) # /*Need to define number of characters for varchar */

BEGIN

  SET @p = node;
  SET @s = '';
  SET @pc = '';
  SET @c = 0;

  label1: LOOP

    IF @p != 'furniture' AND @p IN (@s) = 0 THEN

        SET @c = @c + 1;

        SET @p = ( SELECT parent FROM parentships WHERE child IN (@p) LIMIT 1 );

        SET @s = CONCAT(@s,',',@p);

        IF @c = 2 AND @p IN (@s) = 0 THEN

            SET @pc = ( SELECT child FROM parentships WHERE parent IN (@p) LIMIT 1 );

            SET @s = CONCAT(@s,',',@pc);

        END IF;

        ITERATE label1;

    END IF;

    LEAVE label1;

  END LOOP label1;

    SELECT SUBSTRING(@s,2,100) AS RESULT FROM DUAL; 

END //

DELIMITER ;
创建过程后,可以运行它:

CALL find_all_ancestors('barstool');
还可以查找有关分层检索的内容-。这可能对你有帮助


做这类事情还有很多其他的方法。根据您的需要。

很抱歉让您等了这么久,但为了升级我的PHP配置,我破坏了我的XAMPP,现在我无法访问我的MySQL内容,直到修复为止。-不过,你的方法看起来正是我想要的。特别感谢您的代码内评论。很抱歉这么晚才回复您,但这正是我最终经常设置和使用的内容(不记得设置时遇到了什么挑战)。问题得到了回答。
CALL find_all_ancestors('barstool');