在ERP系統中常常要用到BOM, 但如何展開一個BOM,是很多人很痛苦的一件事情,常常要寫一大堆的程序,其結果還是非常慢,通常跑出一個一階BOM出來要花幾個小時的時間。
如果你的數據庫系統是 Oracle 8i,那麽你將不必再為這種事情煩惱,使用 Hierarchical Queries,你將輕而易主的展出一個BOM來。
上階展下階:
select level lev,b.field01 father,b.field03 child,field07 base,field06,to_char(1||sys_connect_by_path(decode(trim(field10),'KPC',1000*field06,'KP',1000*field06,field06),'*')) total_usage,decode(trim(field10),'KPC','PC','KP','PC',field10) unit
from bom_table b start with field01='XX-XXXX-XX'
connect by prior field03=field01
下階找上階:
select level lev,b.field01 father,b.field03 child,decode(trim(field10),'KPC',1000*field06,'KP',1000*field06,field06) usage,to_char(1||sys_connect_by_path(decode(trim(field10),'KPC',1000*field06,'KP',1000*field06,field06),'*')) total_usage,field07 base,decode(trim(field10),'KPC','PC','KP','PC',field10) unit
from bom_table b start with field03='YY-YYYY-YY'
connect by prior field01=field03
註釋一: XX-XXXX-XX 需要展開的最上層成品料
YY-YYYY-YY 需要展開的最下層元件料號
field01: 主件料件編號 field03 元件料件編號 field06 組成用量 field07 底數 field10 發料單位
註釋二: Sql中的Decode是為了統一單位.total_usage是最終的組成用量,其結果是一個以乘號表示的表達式,因爲無現成方法轉換,故最終還是需要在程式中進行結算。
以上为我在实际操作中的例子,以下为网友流方写的文章,表述更加清楚。仅做参考。
=================================================================================
http://blog.csdn.net/Drate/services/trackbacks/51233.aspx
最近收到网友一个问题,关于Oracle的层次查询的问题,发现Oracle 8i中一个非常有用的查询子句:
select level,rowid,...
from ...
where ...
start with ...
connect by expression;
语法说明:
*****************************************************
start with ...
connect by
(这是一个字句,不能拆开来写)
语法的详细参考,请参考 ORACLE Release 8.0.5 Documentation Library中的 SELECT 帮助
文件位置 doc/database.804/a58225/ch4l.htm
简单说明:
start with ... connect by : 建立一个层次查询("Hierarchical Queries")
start with ... 子句:用户根记录的条件
connect by 子句:用于子记录合父记录的连接方式。是一个特定的条件表达式,必须为其中之一:
PRIOR expr comparison_operator expr
expr comparison_operator PRIOR expr
如果定义了start with... connect by子句,level就返回当前记录的层次号。
*****************************************************
这个语法通过定义一个cursor或视图就可以得到一个层次型的结果集,非常有用,特别是对于象生产企业的EBOM树的生成而言,
将明显改变BOM树生成的执行效率,因此,我将这个语法的内容做了分析:
给定这样的数据:
DOC_PR DOC_CH TITLE
--------- -------------------- -----------------------
DOC A A类
A A2 A-2
A A3 A-3
A A1 A-1
A1 A11 A1-1
DOC B B类
B B1 B-1
B B2 B-2
B B3 B-3
B3 B31 B-3-1
DOC C C类
C C1 test C1
定义一个cursor
Declare curTree Cursor For
select level, doc_ch, title, rowid
from doc_tree
start with doc_pr = 'DOC'
connect by doc_pr = Prior doc_ch;
返回结果集如下:
LEVEL DOC_CH TITLE ROWID
-------- -------------------- ---------------------------------------- ------------------
1 A A类 AAAAi+AADAAAAyNAAE
2 A2 A-2 AAAAi+AADAAAAyNAAM
2 A3 A-3 AAAAi+AADAAAAyNAAN
2 A1 A-1 AAAAi+AADAAAAyNAAP
3 A11 A1-1 AAAAi+AADAAAAyNAAS
1 B B类 AAAAi+AADAAAAyNAAF
2 B1 B-1 AAAAi+AADAAAAyNAAO
2 B2 B-2 AAAAi+AADAAAAyNAAQ
2 B3 B-3 AAAAi+AADAAAAyNAAR
3 B31 B-3-1 AAAAi+AADAAAAyNAAB
1 C C类 AAAAi+AADAAAAyNAAG
2 C1 test C1 AAAAi+AADAAAAyNAAC
这段语法的ORACLE内部逻辑我分析如下:
选择 level,doc_ch,title,rowid
从 doc_tree
以 doc_pr = "DOC"开始
用 doc_pr = 上一个结果的 doc_ch来连接
取出第一个结果集后, as_start自动转换为 当前行的 doc_ch,然后执行
select level, doc_ch, title, rowid
from doc_tree where doc_pr = prior doc_ch
这样循环本层次结果集,然后再开始下一个结果集的处理。
这是内部的逻辑,而返回给用户的是一个按层次完成的结果集
有了这样一个结果集,对于建立treeview是非常方便的,只要循环所有记录就可以轻松实现了。
在Sybase,MS SQL Server中不知有没有这样的语法,我不是太清楚,如果您知道,请告诉我。
现在我在MS SQL Server中的实现是这样的:
加入字段level而不是伪列。实现原理同上面是一致的。