2

我有一个表结构,如(简化):

内容

 - id_content
 - my_string1
 - ...

content_has_content

  - id_content
  - id_subcontent

topic_has_content

  - id_topic
  - id_content

任何主题都可以有多个“内容”,任何“内容”都可以有多个“子内容”(内容的实例)。对于给定的 id_topic,我想从链接的内容、子内容、子内容的子内容等中接收所有 my_string1 的列表。

我知道“WITH”不适用于 mysql,但找不到一个好的递归替代方案。

谢谢丹尼尔

4

2 回答 2

1

MySQL 中没有递归,而且你得到的结果也是平坦的(没有结构)。最好的方法仍然是 PHP、Java 或您使用的任何编程语言中的 while 循环。

查询可能如下所示:

SELECT C.*, CHC.ID_SUBCONTENT
FROM CONTENT C
LEFT OUTER JOIN CONTENT_HAS_CONTENT CHC ON CHC.ID_CONTENT = C.ID_CONTENT
WHERE C.ID = ?
... // you get the idea

在 PHP 中,您可以使用下一个 sub_content_id 重复查询,直到ID_SUBCONTENT is null

于 2013-04-15T15:49:38.307 回答
0

解决方案

PosgreSQL、Oracle、MS-SQL……必须WITH RECURSIVE处理这样的数据结构。它在内部使用一个while循环来获取parent ids当前行的所有内容(我们需要孩子在这里)

这也可以实现MySQL,您可以创建stored procedure并重现相同的行为

假定/使用 DDL

content_has_content条目为

content_1
  content_2
    content_3
      content_4

我通过id_contentas 2 并获得输出为

  content_2
    content_3
      content_4

以上皆为后代content_2

触发call content_details(2);以获取传递的所有子行id_content

SQL

###### Stored Routine
DELIMITER //  
drop procedure IF EXISTS `content_details`;
CREATE DEFINER=`root`@`localhost` PROCEDURE `content_details`(`_idcontent` INT)
    LANGUAGE SQL
    DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN
DECLARE  temp_content_ids varchar(200);
DECLARE idcontent, idcontent2 integer;

SET temp_content_ids= _idcontent;
SET idcontent       = _idcontent;
SET idcontent2      = _idcontent;

WHILE idcontent2 IS NOT NULL DO 
    SET idcontent = NULL;
    SELECT id_subcontent, CONCAT(id_subcontent,',',temp_content_ids) INTO idcontent, temp_content_ids FROM content_has_content WHERE id_content = idcontent2;
    SET idcontent2 = idcontent;
END WHILE;  

SELECT my_string1 FROM content WHERE FIND_IN_SET( id, temp_content_ids );
END//

我基本上做的是运行 awhile loop直到我有最后一个child_id,将它们存储ids在 acomma separated string format然后触发查询以获取我刚刚创建id的所有行var

注意:您的表中可能有无效值,例如行有 a id_subcontent,它指向它自己的id_content,这可能导致过程中永无止境loop,为避免这种情况,您可以使用计数器并限制嵌套说大约 50(或根据您的要求的任何值),raise a exception如果超过该限制

一些数据可以玩..

###### DLL Statements
CREATE TABLE content
( id_content int,
my_string1 varchar(200));

CREATE TABLE content_has_content
( id_content int,
  id_subcontent  int);

CREATE TABLE  topic_has_content
( id_topic int,
 id_content int);


INSERT INTO content VALUES (1, 'content_1'), (2, 'content_2'), (3, 'content_3'), (4, 'content_4');
INSERT INTO content_has_content VALUES (1, 2), (2, 3), (3, 4);
INSERT INTO topic_has_content VALUES (1, 1);

希望这可以帮助..

于 2013-04-15T19:42:30.560 回答