Mysql 具有对同一表的多个引用的SQL递归查询

Mysql 具有对同一表的多个引用的SQL递归查询,mysql,sql,recursive-query,Mysql,Sql,Recursive Query,有没有办法通过某种递归SQL查询(MySQL)而不是通过编程来解决这个问题 我有两个表,一个包含包id和名称,另一个包含包id和父\u id,这也是对其他包id的引用。我需要实现的是获取包含特定包的包的所有id的列表 如果我正在寻找id为8的包,下面是一个表和所需输出的示例。包8是包5和包6的一部分,但包6是包1和包4的一部分。所以,我需要所有这些ID作为数组(1,4,5,6) 套餐表: +----+-----------+ | id | name | +----+----------

有没有办法通过某种递归SQL查询(MySQL)而不是通过编程来解决这个问题

我有两个表,一个包含包id和名称,另一个包含包id和父\u id,这也是对其他包id的引用。我需要实现的是获取包含特定包的包的所有id的列表

如果我正在寻找id为8的包,下面是一个表和所需输出的示例。包8是包5和包6的一部分,但包6是包1和包4的一部分。所以,我需要所有这些ID作为数组(1,4,5,6)

套餐表:

+----+-----------+
| id | name      |
+----+-----------+
| 1  | package 1 |
| 2  | package 2 |
| 3  | package 3 |
| 4  | package 4 |
| 5  | package 5 |
| 6  | package 6 |
| 7  | package 7 |
| 8  | package 8 |
+----+-----------+
表的第u部分:

+----+-----------+
| id | parent_id |
+----+-----------+
| 6  |     1     |
| 6  |     4     |
| 8  |     5     |
| 8  |     6     |
+----+-----------+
输出:

+----+
| id |
+----+
| 1  |
| 4  |
| 5  |
| 6  |
+----+

编辑:为了更好地解释这一切是怎么回事。这个包表实际上是汽车零件表,它还包括价格和更多字段。如果我们寻找“正时皮带”部件,它可以是独立的,可以是某个捆绑包的一部分,我们称之为“正时皮带套件”,也可以是车间“全方位服务”的一部分。所有“正时皮带”、“正时皮带组”、“全套服务”都存储在同一张表中。现在,当客户要求购买“同步带”时,我可以为他单独提供50美元或成套提供150美元,或者我可以为他提供250美元的全面服务。所有这些都包括他要求的“同步带”。

为什么不使用表中的部分两次呢?联接表本身的部分
自联接
,然后查询id?我想这真的取决于你在寻找什么级别的递归

您应该能够通过以下方式实现:

| parent_id |
| --------- |
| 5         |
| 6         |
| 1         |
| 4         |
| parent_id | name      |
| --------- | --------- |
| 1         | package 1 |
| 4         | package 4 |
| 5         | package 5 |
| 6         | package 6 |

您可以
将结果与
产品
表连接,以显示每个父产品的名称:

WITH RECURSIVE cte AS (
    SELECT id, parent_id FROM part_of WHERE id = 8
    UNION ALL
    SELECT po.id, po.parent_id FROM part_of po INNER JOIN cte ON cte.parent_id = po.id
)
SELECT cte.parent_id, p.name
FROM cte
INNER JOIN packages p on cte.parent_id = p.id

| parent_id |
| --------- |
| 5         |
| 6         |
| 1         |
| 4         |
| parent_id | name      |
| --------- | --------- |
| 1         | package 1 |
| 4         | package 4 |
| 5         | package 5 |
| 6         | package 6 |

我在编写这个答案时假设您将需要packages表来获取ID,然后将使用ID从表的part_获取parent_ID。这部分在你的问题中有点不清楚。如果我的假设是错误的,那么@GBM答案将和我的一样有效

WITH PACKAGES_CTE AS (
    SELECT PACKAGES.ID, PACKAGES.NAME
    FROM PACKAGES
), PACKAGES2_CTE AS
    (
        SELECT *
        FROM PACKAGES2
    )

SELECT P2.PARENT_ID
FROM PACKAGES2_CTE P2
LEFT JOIN PACKAGES2_CTE P3 ON P3.PARENT_ID = P2.ID
WHERE P3.ID = 8

UNION ALL

SELECT P2.PARENT_ID
FROM PACKAGES_CTE P
LEFT JOIN PACKAGES2_CTE P2 ON P.ID = P2.ID
WHERE P2.ID = P2.PARENT_ID OR P.ID = 8
如果您有任何问题,请随时提问。我使用您提供的样本数据进行了测试。因为我已经知道ID,所以我不需要使用Packages.Name。我假设您希望使用Packages.Name='Package 8'而不是P.ID=8


这是一个有趣的问题

您是否尝试过编写查询?发布您尝试过的内容和您遇到的困难,我们可以尝试提供帮助。不,我没有,因为我不太熟悉sql查询。所以我在php中编写了递归函数,它使用了更简单的查询。获取id 8的所有父id,然后再次调用每个父id函数。所有函数调用的结果都合并到一个主数组中。MySQL仅支持v8+中的递归CTE。你用的是什么版本?并且有递归CTE,这将使这个答案非常简单。mysql版本8.0.15 for Linux on x86_64(mysql Community Server-GPL)我很确定他仍然需要查看packages表。我举他的例子,他使用包8。我假设他想获得包8的ID,然后加入表的part_。我可能错了,希望@IgorPejašinović能提供一些见解。@GMB的第一个解决方案是正确的答案。套餐表只是为了感受这一切。我使用它只是为了找到起始id。packages表就是为了对这是什么有一些感觉。我使用它只是为了找到起始id。对于您的解决方案,我在第一篇文章中得到了我想要的这个示例的结果,但是如果我在的第_部分添加新行,假设包4有父2,它将停止工作。这就是为什么我认为,它一定是某种递归查询。