Mysql 如何创建一个SQL调用,递归地将不同的ID和父ID合并到一个列中?

Mysql 如何创建一个SQL调用,递归地将不同的ID和父ID合并到一个列中?,mysql,sql,recursive-query,lookup-tables,Mysql,Sql,Recursive Query,Lookup Tables,我有一个公司表,它引用自身,如下所示: company_id parent_id ----------------------- 1 (NULL) 2 1 3 2 4 1 5 (NULL) 所以一个公司可以有一个母公司公司等等 我还有一个查找表,可以将客户连接到与其相关的公司,例如: customer_id com

我有一个
公司
表,它引用自身,如下所示:

company_id    parent_id
-----------------------
1             (NULL)   
2             1        
3             2             
4             1
5             (NULL)
所以一个
公司
可以有一个母公司
公司
等等

我还有一个查找表,可以将
客户
连接到与其相关的
公司
,例如:

customer_id     company_id
--------------------------
1               1
1               3
1               4
2               3
2               2
我正在尝试创建一个SQL调用,该调用将获取与客户id相关的不同公司id的列表。这意味着我不仅需要从查找表中获取一对一关系的公司id,还需要运行所有父项,如果父项id不在列表中,则添加父项id,然后查看父项的父项,如果他们不在列表中,则添加他们的ID,以此类推

因此,例如,在上表中,如果我试图查找所有公司id的
,其中customer\u id=2
,我希望返回:

company_id
---------------
1
2
3
注意,它递归地得到了1,但并没有列出2两次,因为它只查找不同的id


但是,当涉及到递归SQL调用时,我非常困惑。这是可能的还是我应该在代码中这样做?

在MySQL 8.0及更高版本中,您可以使用递归CTE遍历层次结构。但由于您的客户已经有了他们指定公司的母公司(这对我来说有点奇怪),这将导致重复。所以你需要得到不同的集合。为了方便起见,我使用了另一个CTE,但您也可以跳过它,直接在查询中执行
DISTINCT
。然后,您可以简单地从CTE查询客户的公司

WITH RECURSIVE
cte1 AS
(
SELECT cu.customer_id,
       cu.company_id
       FROM customer cu
UNION ALL
SELECT ct.customer_id,
       co.parent_id company_id
       FROM cte1 ct
            INNER JOIN company co
                       ON ct.company_id = co.company_id
       WHERE co.parent_id IS NOT NULL
),
cte2 AS
(
SELECT DISTINCT
       ct.customer_id,
       ct.company_id
       FROM cte1 ct
)
SELECT company_id
       FROM cte2
       WHERE customer_id = 2;


当然,您也可以将客户ID上的条件转移到递归CTE的锚中。如果您只需要为一个客户进行查询,那么这可能会降低查询成本。

在MySQL 8.0及更高版本中,您可以使用递归CTE遍历层次结构。但由于您的客户已经有了他们指定公司的母公司(这对我来说有点奇怪),这将导致重复。所以你需要得到不同的集合。为了方便起见,我使用了另一个CTE,但您也可以跳过它,直接在查询中执行
DISTINCT
。然后,您可以简单地从CTE查询客户的公司

WITH RECURSIVE
cte1 AS
(
SELECT cu.customer_id,
       cu.company_id
       FROM customer cu
UNION ALL
SELECT ct.customer_id,
       co.parent_id company_id
       FROM cte1 ct
            INNER JOIN company co
                       ON ct.company_id = co.company_id
       WHERE co.parent_id IS NOT NULL
),
cte2 AS
(
SELECT DISTINCT
       ct.customer_id,
       ct.company_id
       FROM cte1 ct
)
SELECT company_id
       FROM cte2
       WHERE customer_id = 2;


当然,您也可以将客户ID上的条件转移到递归CTE的锚中。如果您只需要为一个客户进行查询,那么这可能会降低查询成本。

哪个版本的MySQL?CTE(common table expressions)能够做到这一点是最近才引入的。如果问题只是如何执行查询的递归部分,那么答案是下面的问题:MySQL的哪个版本可能重复?CTE(common table expressions,通用表表达式)最近才被引入。如果问题只是如何执行查询的递归部分,那么答案就是下面的问题:可能重复