背景
有如下的bom 表,parent_part 與child_part 是多對多的關係,現在要求查詢出每個child_part 的最頂層的 parent_part
create
table pl_bom(
parent_part varchar
(10),
child_part varchar
(10))
insert
into pl_bom
select
'a',
'c'union
allselect
'b',
'c'union
allselect
'c',
'd'union
allselect
'd',
'e'union
allselect
'd',
'f'union
allselect
'h',
'f'
即根據上述資料,應該得到如下結果
child_part parent_part
---------- -----------
c ac b
d ad b
e ae b
f af b
f h
處理方法
一般可能會考慮從 child_part 開始掃瞄的方法。但對於每個child_part 而言,它有一至多個 parent_part,對於多個parent_part 而言,每個 parent_part 到最頂部的 parent_part 經過的層數還可能不一致,這會導致掃瞄演算法不太好寫,而且同乙個 parent_part 如果被多個 child_part 引用的話, 還可能導致重複的搜尋此 parent_part 的頂 parent_part。
下面的演算法採用自 parent_part 反推 child_part 的方式,可以避免重複掃瞄某個 parent_part 到 child_part 的問題
-- 使用自頂向下展開
-- 因為要刪除資料, 所以不能用原始表, 用個臨時表
select
id =
identity
(int
, 1,1 ), child_part, parent_part
into#
from
pl_bom
-- 從頂往下展
declare
@level int
set@level = 1
select
id = id * 1,
level
= @level,
child_part, parent_part
into
#re
from
# a
where
notexists(
select
*from #
where child_part = a.parent_part)
while
@@rowcount
> 0
begin
set @level = @level + 1
delete a
from # a, #re b
where a.id = b.id
and b.level = @level - 1
insert #re(
id,level
,child_part, parent_part)
select
a.id, @level,
a.child_part, b.parent_part
from # a, #re b
where a.parent_part = b.child_part
and b.level = @level - 1
end
-- 顯示結果
select
child_part, parent_part
from
#re
order
by 1, 2
-- 刪除臨時表
drop
table #re, #
使用臨時表 迴圈展 BOM
背景 有如下的 bom 表,parent part 與child part 是多對多的關係,現在要求查詢出每個 child part 的最頂層的 parent part create table pl bom parent part varchar 10 child part varchar 10 ...
使用臨時表 迴圈展 BOM
背景 有如下的 bom 表,parent part 與child part 是多對多的關係,現在要求查詢出每個 child part 的最頂層的 parent part create table pl bom parent part varchar 10 child part varchar 10 ...
使用臨時表 迴圈展 BOM
背景 有如下的 bom 表,parent part 與child part 是多對多的關係,現在要求查詢出每個 child part 的最頂層的 parent part create table pl bom parent part varchar 10 child part varchar 10 ...