在同一 table 中查找所有没有直接 id-parentid 的祖先
Find all ancestors without direct id-parentid in same table
我有一个跨越两个 table 的 parent-child 结构。第一个 table 有 BOM_ID 的帐单和 ITEM_ID 的相关 children 项目。另一个 parent 项目有 BOM_ID 和 ITEM_ID。
我可以通过以下查询找到 parents' ITEM_ID 的第一层
SELECT item_id
FROM bomversion
WHERE bom_id IN (SELECT bom_id FROM bom WHERE item_id = 1)
所以,为了找到所有的祖先,我将不得不重复这一步。我试图查看 CTE 和递归技术,但所有示例在相同的 table 中都有 parentid 和 childid。我想不通这个。
如果1是2的child,2是3的child,3是4的child,2也是5的child,我是查找以下结果:
ChildID
ParentID
1
2
2
3
2
5
3
4
起点将是一个特定的 ChildID。
解决方案
根据 Adnan Sharif 的建议,我找到了解决问题的方法:
WITH items_CTE AS (
-- create the mapping of items to consider
SELECT
B.ITEMID AS Child_id,
BV.ITEMID AS Parent_Id
FROM BOM AS B
INNER JOIN BOMVERSION AS BV
ON B.BOMID = BV.BOMID
), parent_child_cte AS (
-- select those items as initial query
SELECT
Child_id,
Parent_id
FROM items_CTE
WHERE Child_id = '111599' -- this is the starting point
UNION ALL
-- recursive approach to find all the ancestors
SELECT
c.Child_Id,
c.Parent_Id
FROM items_CTE c
JOIN parent_child_cte pc
ON pc.Parent_Id = c.Child_id
)
SELECT * FROM parent_child_cte
根据您在评论中分享的 dbfiddle,如果我理解正确的话,您想要显示 child 的所有 parents 的行。
例如,让我们考虑层次结构,1 是 2 的 child,2 是 3 的 child,3 是 4 的 child。您希望最终结果为,
child_id
parent_id
1
2
1
3
1
4
2
3
2
4
3
4
如果是这样,我们可以使用递归 CTE 来构建 table。首先,我们需要基于 bom_id
在这两个 table 之间建立关系,然后我们需要找出 parent-child 关系。之后,我们将根据初始查询添加行。请看下面的代码。
WITH RECURSIVE items_CTE AS (
-- create the mapping of items to consider
SELECT
B.Item_id AS Child_id,
BV.Item_id AS Parent_Id
FROM BOM AS B
INNER JOIN BOMVERSION AS BV
ON B.bom_id = BV.bom_id
), parent_child_cte AS (
-- select those items as initial query
SELECT
Child_id,
Parent_id
FROM items_CTE
UNION
-- recursive approach to find all the ancestors
SELECT
parent_child_cte.Child_Id,
items_CTE.Parent_Id
FROM items_CTE
INNER JOIN parent_child_cte
ON parent_child_cte.Parent_Id = items_CTE.Child_id
)
SELECT * FROM parent_child_cte
我有一个跨越两个 table 的 parent-child 结构。第一个 table 有 BOM_ID 的帐单和 ITEM_ID 的相关 children 项目。另一个 parent 项目有 BOM_ID 和 ITEM_ID。
我可以通过以下查询找到 parents' ITEM_ID 的第一层
SELECT item_id
FROM bomversion
WHERE bom_id IN (SELECT bom_id FROM bom WHERE item_id = 1)
所以,为了找到所有的祖先,我将不得不重复这一步。我试图查看 CTE 和递归技术,但所有示例在相同的 table 中都有 parentid 和 childid。我想不通这个。
如果1是2的child,2是3的child,3是4的child,2也是5的child,我是查找以下结果:
ChildID | ParentID |
---|---|
1 | 2 |
2 | 3 |
2 | 5 |
3 | 4 |
起点将是一个特定的 ChildID。
解决方案
根据 Adnan Sharif 的建议,我找到了解决问题的方法:
WITH items_CTE AS (
-- create the mapping of items to consider
SELECT
B.ITEMID AS Child_id,
BV.ITEMID AS Parent_Id
FROM BOM AS B
INNER JOIN BOMVERSION AS BV
ON B.BOMID = BV.BOMID
), parent_child_cte AS (
-- select those items as initial query
SELECT
Child_id,
Parent_id
FROM items_CTE
WHERE Child_id = '111599' -- this is the starting point
UNION ALL
-- recursive approach to find all the ancestors
SELECT
c.Child_Id,
c.Parent_Id
FROM items_CTE c
JOIN parent_child_cte pc
ON pc.Parent_Id = c.Child_id
)
SELECT * FROM parent_child_cte
根据您在评论中分享的 dbfiddle,如果我理解正确的话,您想要显示 child 的所有 parents 的行。 例如,让我们考虑层次结构,1 是 2 的 child,2 是 3 的 child,3 是 4 的 child。您希望最终结果为,
child_id | parent_id |
---|---|
1 | 2 |
1 | 3 |
1 | 4 |
2 | 3 |
2 | 4 |
3 | 4 |
如果是这样,我们可以使用递归 CTE 来构建 table。首先,我们需要基于 bom_id
在这两个 table 之间建立关系,然后我们需要找出 parent-child 关系。之后,我们将根据初始查询添加行。请看下面的代码。
WITH RECURSIVE items_CTE AS (
-- create the mapping of items to consider
SELECT
B.Item_id AS Child_id,
BV.Item_id AS Parent_Id
FROM BOM AS B
INNER JOIN BOMVERSION AS BV
ON B.bom_id = BV.bom_id
), parent_child_cte AS (
-- select those items as initial query
SELECT
Child_id,
Parent_id
FROM items_CTE
UNION
-- recursive approach to find all the ancestors
SELECT
parent_child_cte.Child_Id,
items_CTE.Parent_Id
FROM items_CTE
INNER JOIN parent_child_cte
ON parent_child_cte.Parent_Id = items_CTE.Child_id
)
SELECT * FROM parent_child_cte