如何创建一个 SQL 调用,它将递归地获取 DISTINCT id 和 parent id 组合成一个列?
How to create a SQL call that will recursively get DISTINCT ids and parent ids combined into a single column?
我有一个引用自身的 company
table,像这样:
company_id parent_id
-----------------------
1 (NULL)
2 1
3 2
4 1
5 (NULL)
所以 company
可以有 parent company
等等。
我也有一个查找 table 将 customer
连接到他们相关的 company
,像这样:
customer_id company_id
--------------------------
1 1
1 3
1 4
2 3
2 2
我正在尝试创建一个 SQL 调用,它将获得与 customer_id 相关的不同 company_id 的列表。这意味着我不仅需要从查找 table 中获取一对一关系的公司 ID,还需要通过所有 parent 获取 运行,添加 parent如果它们不在列表中,请添加 ID,然后查看 parents' parents,如果它们不在列表中,请添加它们的 ID,依此类推。
例如,在上面的 table 中,如果我试图找到所有 company_id 的 where customer_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;
DB Fiddle
当然,您也可以将客户 ID 的条件转移到递归 CTE 的锚点中。如果您只需要为一个客户查询,这可能会降低查询成本。
我有一个引用自身的 company
table,像这样:
company_id parent_id
-----------------------
1 (NULL)
2 1
3 2
4 1
5 (NULL)
所以 company
可以有 parent company
等等。
我也有一个查找 table 将 customer
连接到他们相关的 company
,像这样:
customer_id company_id
--------------------------
1 1
1 3
1 4
2 3
2 2
我正在尝试创建一个 SQL 调用,它将获得与 customer_id 相关的不同 company_id 的列表。这意味着我不仅需要从查找 table 中获取一对一关系的公司 ID,还需要通过所有 parent 获取 运行,添加 parent如果它们不在列表中,请添加 ID,然后查看 parents' parents,如果它们不在列表中,请添加它们的 ID,依此类推。
例如,在上面的 table 中,如果我试图找到所有 company_id 的 where customer_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;
DB Fiddle
当然,您也可以将客户 ID 的条件转移到递归 CTE 的锚点中。如果您只需要为一个客户查询,这可能会降低查询成本。