如何创建将递归地将DISTINCT ID和父ID合并到单个列中的SQL调用?

时间:2019-01-08 00:07:06

标签: mysql sql recursive-query lookup-tables

我有一个引用自己的company表,如下所示:

company_id    parent_id
-----------------------
1             (NULL)   
2             1        
3             2             
4             1
5             (NULL)

因此company可以有一个父company,依此类推。

我还有一个查找表,用于将customer连接到与其相关的company,例如:

customer_id     company_id
--------------------------
1               1
1               3
1               4
2               3
2               2

我正在尝试创建一个SQL调用,该调用将获取与customer_id相关的不同company_id的列表。这意味着我不仅需要从查找表中获取一对一关系的公司ID,还需要遍历所有父项,如果父项ID不在列表中,则添加它们,然后查看父项父母,如果他们的ID不在列表中,则添加他们的ID,依此类推。

因此,例如,在上表中,如果我尝试查找所有company_id的where customer_id = 2,我希望会回来:

company_id
---------------
1
2
3

请注意,它递归地得到1,但是它没有两次列出2,因为它只是在寻找不同的ID。

但是,当涉及到递归SQL调用时,我非常迷茫。这可能还是我应该在代码中完成?

1 个答案:

答案 0 :(得分:3)

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

ListenableWorker.startWork() documentation
当然,您也可以将客户ID上的条件转移到递归CTE的锚点中。如果您只需要一个客户就可以减少查询的费用。