我不熟悉的火鳥,但這部作品在SQL Server中,所以是希望類似/足以讓您的軌道上:
WITH TEST (IDRoot, IDPARENT, IDCHILD) AS
(
SELECT P0.IDPROD, C0.IDParent, C0.IDCHILD
FROM PROD AS P0
left outer join COMP C0 on C0.IDParent = P0.IDPROD
WHERE P0.IDProd not in (select IDChild from COMP)
UNION ALL
SELECT T.IDRoot, C1.IDPARENT, C1.IDCHILD
FROM COMP AS C1
inner join TEST AS T on T.IDCHILD = C1.IDPARENT
)
SELECT * FROM TEST
希望有所幫助。
SQL小提琴版本:http://sqlfiddle.com/#!6/22f84/7
注意
Includ列來表示樹的根,以及父/子 - 因爲可能有多個樹,如果我們不指定特定的根:
WITH TEST (IDRoot, IDPARENT, IDCHILD) AS
治療任何產品,其是不是小孩作爲根(即,第一項在樹)。
WHERE P0.IDProd not in (select IDChild from COMP)
編輯:回答任何節點以查看其所有的親戚在評論
查詢:
簡單的方法來過濾任何節點上會修改上面的語句的WHERE P0.IDProd not in (select IDChild from COMP)
與WHERE P0.IDProd = IdImInterestedIn
。但是,如果您想使用CTE查看視圖,則可以通過此靜態查詢運行查詢,您可以使用下面的代碼 - 然後,您可以在IDProd
(select * from test where IDProd = IdImInterestedIn
)上篩選以查看該項目的祖先和後代。
WITH TEST (IDProd, IDRelation, Generation) AS
(
SELECT IDPROD
, IDPROD
, 0
FROM PROD
UNION ALL
SELECT T.IDPROD
, C.IdParent
, T.Generation - 1
FROM TEST AS T
inner join Comp as C
on C.IdChild = T.IDRelation
where t.Generation <= 0
UNION ALL
SELECT T.IDPROD
, C.IdChild
, T.Generation + 1
FROM TEST AS T
inner join Comp as C
on C.IdParent = T.IDRelation
where t.Generation >= 0
)
SELECT *
FROM TEST
order by IDProd, Generation
SQL小提琴:http://sqlfiddle.com/#!6/22f84/15
見根節點的全樹一列
WITH TEST (IDRoot, IDPARENT, IDCHILD, TREE) AS
(
SELECT P0.IDPROD, C0.IDParent, C0.IDCHILD, cast(P0.IDPROD as nvarchar(max)) + coalesce(', ' + cast(C0.IDCHILD as nvarchar(max)),'')
FROM PROD AS P0
left outer join COMP C0 on C0.IDParent = P0.IDPROD
WHERE P0.IDProd not in (select IDChild from COMP)
UNION ALL
SELECT T.IDRoot, C1.IDPARENT, C1.IDCHILD, TREE + coalesce(', ' + cast(C1.IDCHILD as nvarchar(max)),'')
FROM COMP AS C1
inner join TEST AS T on T.IDCHILD = C1.IDPARENT
)
SELECT *
FROM TEST
order by IDRoot
SQL小提琴:http://sqlfiddle.com/#!6/22f84/19
編輯:回答到其他意見
with cte (tree_root_no, tree_row_no, relation_sort, relation_chart, Name, id, avoid_circular_ref) as
(
select row_number() over (order by p.idprod)
, 1
, cast(row_number() over (order by p.idprod) as nvarchar(max))
, cast('-' as nvarchar(max))
, p.NAME
, p.IDPROD
, ',' + cast(p.IDPROD as nvarchar(max)) + ','
from PROD p
where p.IDPROD not in (select IDCHILD from COMP) --if it's nothing's child, it's a tree's root
union all
select cte.tree_root_no
, cte.tree_row_no + 1
, cte.relation_sort + cast(row_number() over (order by p.idprod) as nvarchar(max))
, replace(relation_chart,'-','|') + ' -'
, p.NAME
, p.IDPROD
, cte.avoid_circular_ref + cast(p.IDPROD as nvarchar(max)) + ','
from cte
inner join COMP c on c.IDPARENT = cte.id
inner join PROD p on p.IDPROD = c.IDCHILD
where charindex(',' + cast(p.IDPROD as nvarchar(max)) + ',', cte.avoid_circular_ref) = 0
)
select tree_root_no, tree_row_no, relation_sort, relation_chart, id, name
from cte
order by tree_root_no, relation_sort
SQL小提琴:http://sqlfiddle.com/#!6/4397f/9
更新,以顯示每路
這一個是一個討厭的黑客,但我能想到的唯一的辦法來解決你的難題;這給每個路徑穿過樹林自己的號碼:
;with inner_cte (parent, child, sequence, treePath) as (
select null
, p.IDPROD
, 1
, ',' + CAST(p.idprod as nvarchar(max)) + ','
from @prod p
where IDPROD not in
(
select IDCHILD from @comp
)
union all
select cte.child
, c.IDCHILD
, cte.sequence + 1
, cte.treePath + CAST(c.IDCHILD as nvarchar(max)) + ','
from inner_cte cte
inner join @comp c on c.IDPARENT = cte.child
)
, outer_cte (id, value, pathNo, sequence, parent, treePath) as
(
select icte.child, p.NAME, ROW_NUMBER() over (order by icte.child), icte.sequence, icte.parent, icte.treePath
from inner_cte icte
inner join @prod p on p.IDPROD = icte.child
where icte.child not in (select coalesce(icte2.parent,-1) from inner_cte icte2)
union all
select icte.child, p.NAME, octe.pathNo,icte.sequence, icte.parent, icte.treePath
from outer_cte octe
inner join inner_cte icte on icte.child = octe.parent and CHARINDEX(icte.treePath, octe.treePath) > 0
inner join @prod p on p.IDPROD = icte.child
)
select id, value, pathNo
from outer_cte
order by pathNo, sequence
SQL小提琴這裏:http://sqlfiddle.com/#!6/5a16e/1
如果你想表示一棵樹,你不需要一個:M的關係,1:N會做因爲所有節點都只有一個(!)父節點(根節點有一個空父節點) – alzaimar
在我的情況下,它必須是多對多的,因爲許多PROD(產品)可以具有相同的COMP(組件)。 – JohnAPaul
ok,從技術上講,它不是一棵樹,而是一個有向圖 – alzaimar