背景
有如下的
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
all
select
'b',
'c'union
all
select
'c',
'd'union
all
select
'd',
'e'union
all
select
'd',
'f'union
all
select
'h',
'f'
即根據上述資料,應該得到如下結果
child_part parent_part
---------- -----------
cacb
dadb
eaeb
fafb
fh處理方法
一般可能會考慮從
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
-- 刪除臨時表
使用臨時表 迴圈展 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 in...