新手——刚开始研究BOM,不对之处还望各位博友不吝赐教
1、创建BOM父项表 ——FID,FItemID
create table HWbom
(
FId int identity(1,1),
FItemID int
)
2、创建BOM子项表 ——FID,FOrgID,FParentID,FLevel,FSN,FItemID,FQty,FBOMInterID,FEntryID
create table HWbomchild
(
FID int identity(1,1),
FOrgID int,
FParentID int,
FLevel int,
FSN nvarchar(200),
FItemID int,
FQty decimal(28,19),
FBOMInterID int,
FEntryID int
)
3、将父项BOM对应的物料内码插入父项表(可带条件)
--t_ICItem——物料表
--t_item——基础资料主表
--icbom——BOM表
--ICBOMGROUP——BOM组别表
--物料表FErpClsID 物料属性(1-外购,2-自制,3-委外加工,5-虚拟件)
--基础资料主表 fdeleted 是否删除(0,未删除)
--基础资料主表 FItemClassID 对应编码:
--1-客户
--2-部门
--3-职员
--4-商品
--5-仓位
--7-单位
--8-供应商
--基础资料主表 FDetail 是否明细(1,明细)
-- delete from HWbom
INSERT INTO HWbom ( FItemID ) SELECT
t.Fitemid
FROM
t_ICItem t --71615
INNER JOIN t_item t5 ON t5.FItemID = t.Fitemid
LEFT JOIN icbom t6 ON t6.fitemid= t.Fitemid
LEFT JOIN ICBOMGROUP t7 ON t7.finterid= t6.fparentid
WHERE
t.FErpClsID IN ( 1, 2, 3, 5 ) --2代表自制件,3代表委外件,5代表虚拟件
AND t5.FItemClassID= 4
AND t5.FDeleted= 0
AND t5.FDetail= 1 --类型是4(商品),未删除,明细是1
--and t5.fnumber in('物料编码1','物料编码2') --可根据需要限定BOM范围
ORDER BY
t.fnumber
4、根据父项表数据,将数据插入子项表,为后续卷算做准备
INSERT INTO HWbomchild ( FOrgID, FParentID, FSN, FItemID, FQty, FBOMInterID, FEntryID, FLevel ) SELECT
FId,- 1 AS FParentID,
'001',
u1.FItemID,
1 AS Fqty,
t1.FInterID AS FBOMInterID,- 1 AS FEntryID,
0
FROM
HWbom u1
LEFT JOIN ICBOM t1 ON u1.FItemID= t1.FItemID
AND t1.FUseStatus= 1072
5、BOM卷算
DECLARE
@LEVEL INT
SET @LEVEL = 1
WHILE
EXISTS (
SELECT 1 FROM HWbomchild
WHERE FLevel = @LEVEL - 1
AND FItemID
IN ( SELECT Fitemid FROM icbom WHERE FUseStatus = 1072 )
)
AND @LEVEL < 20
BEGIN
INSERT INTO HWbomchild ( FOrgID, FParentID, FSN, FItemID, FQty, FBOMInterID, FEntryID, FLevel )
SELECT
u1.FOrgID,
u1.FID,
u1.FSN+ '.' + RIGHT ( '000' + CONVERT ( nvarchar ( 50 ), t2.Fentryid ), 3 ),
t2.Fitemid,
u1.FQty* ( t2.FQty/ t1.FQty ) / ( 1-t2.FScrap/ 100 ),
t2.FInterID,
t2.FEntryID,@LEVEL
FROM
HWbomchild u1
INNER JOIN icbom t1 ON u1.FItemID= t1.FItemID
INNER JOIN ICBOMChild t2 ON t2.FInterID= t1.FInterID
WHERE
u1.FLevel=@LEVEL - 1
AND t1.FUseStatus= 1072
SET @LEVEL =@LEVEL + 1
END
6、最终BOM展开数据检索
SELECT
t2.FModel 专机号,
t4.FBOMNumber BOM编号,
t2.FNumber 产品代码,
t2.FName 产品名称,
t1.FSN 序号,
t3.FNumber 材料代码,
t3.FName 材料名称,
t3.FModel 材料规格,
t1.FQty 产品用量,
yy.fname 材料属性,
t5.FQty 单位用量,
t5.FScrap 损耗率,
t6.FName AS 是否跳层,
t5.FNote 备注,
t5.FPositionNo 位置号
FROM
HWbom u1
INNER JOIN HWbomchild t1 ON u1.FId= t1.FOrgID
INNER JOIN t_icitem t2 ON t2.FItemID= u1.FItemID
INNER JOIN t_ICItem t3 ON t3.FItemID= t1.FItemID
LEFT JOIN ICBOM t4 ON t4.FInterID= t1.FBOMInterID
LEFT JOIN ICBOMChild t5 ON t5.FInterID= t1.FBOMInterID
AND t5.FEntryID= t1.FEntryID
LEFT JOIN t_SubMessage t6 ON t6.FInterID= t4.FBOMSkip
INNER JOIN t_SubMessage yy ON yy.FInterID= t3.FErpClsID
where t2.FModel='EYY33/04/S.515'
AND T4.FUseStatus = 1072
and t4.FBomType <> 3 --FBomType;0-普通,1-配置类,2-生产规划类,3-客户BOM,4-特征类
-- and t4.fitemid=t2.fitemid
-- and t4.FBOMNumber = 'BOM019979'
order by u1.FId,t1.FSN
7、最后清空父项表和子项表数据
TRUNCATE TABLE HWbom --清空附表数据
TRUNCATE TABLE HWbomchild --清空子表数据
8、如果不再使用,可以将这两个表删除
DROP TABLE HWbom --删除父表
DROP TABLE HWbomchild --删除子表
9、依据BOM号或规格型号查询某bom所有层级物料价格——注意这只能查询出BOM字表单层级的
在以上1-8以需求选取基础上创建一个定时任务每天实时同步BOM,其中的参数如下,注释的为依据BOM查询,第一条为规格型号查询
AND t2.FModel='ATD60L/19.300.E01'
-- and t4.fitemid=t2.fitemid
-- and t4.FBOMNumber = 'BOM019979'
with bb as(
(
select
t2.FModel 专机号,
t4.FBOMNumber BOM编号,
t2.FNumber 产品代码,
t2.FName 产品名称,
t1.FSN 序号,
t3.FNumber 材料代码,
t3.FName 材料名称,t3.FModel 材料规格
,t1.FQty 产品用量,yy.fname 材料属性,
t5.FQty 单位用量,
t5.FScrap 损耗率,
t6.FName as 是否跳层,
t5.FNote 备注,
t5.FPositionNo 位置号
from HWbom u1
inner join HWbomchild t1 on u1.FId=t1.FOrgID
inner join t_icitem t2 on t2.FItemID=u1.FItemID
inner join t_ICItem t3 on t3.FItemID=t1.FItemID
left join ICBOM t4 on t4.FInterID=t1.FBOMInterID
left join ICBOMChild t5 on t5.FInterID=t1.FBOMInterID and t5.FEntryID=t1.FEntryID
left join t_SubMessage t6 on t6.FInterID=t4.FBOMSkip
inner join t_SubMessage yy on yy.FInterID=t3.FErpClsID
--left join pp on pp.FNumber=t3.FNumber
where T4.FUseStatus = 1072 and t4.FBomType <> 3 --FBomType;0-普通,1-配置类,2-生产规划类,3-客户BOM,4-特征类
AND t2.FModel='ATD60L/19.300.E01'
-- and t4.fitemid=t2.fitemid
-- and t4.FBOMNumber = 'BOM019979'
))
select bb.*,pp.FName,pp.FPrice from bb
left join (
select zz.*
from(
SELECT v1.FNumber AS FSupplyNumber,t1.FModel,v1.FName,
u1.FPrice,
t1.FNumber AS FItemNumber,
u1.FLastModifiedDate,
t1.FName AS FItemName, row_number ( ) OVER ( partition BY t1.FNumber,v1.FNumber ORDER BY u1.FLastModifiedDate DESC ) Suquence
FROM t_SupplyEntry u1 INNER JOIN t_Supplier v1 ON u1.FSupID=v1.FItemID
INNER JOIN t_Supply u2 ON u1.FSupID = u2.FSupID AND u1.FItemID=u2.FItemID AND u1.FPType=u2.FPType
INNER JOIN t_ICItem t1 ON u2.FItemID = t1.FItemID
INNER JOIN t_MeasureUnit t2 ON u1.FUnitID = t2.FItemID
INNER JOIN t_Currency t3 ON u1.FCyID = t3.FCurrencyID
INNER JOIN t_Currency u3 ON u3.FCurrencyID = u2.FCurrencyID
LEFT JOIN ICSupOperation t7 on u1.FEntryID=t7.FID
LEFT JOIN t_item t5 ON t1.FParentID=t5.FItemID
LEFT JOIN t_User U ON u1.FLastModifiedBy = U.FUserID
LEFT JOIN t_SubMessage t8 ON t7.FOpID=t8.FInterID
LEFT JOIN t_User uu ON uu.FUserID <> 0 AND u1.FCheckerID = uu.FUserID
WHERE v1.FStatus<>1074 and u1.FPType = '1'
)zz
where zz.Suquence=1
)pp on bb.材料代码=pp.FItemNumber
10、若要实现多级展开需要捋顺BOM的层级逻辑关系
BOM主表与子表之间可能只是存储了一层的关联关系;通过BOM主子表关联出来这一层后,这一层中所包含的物料很可能是个组件对应的是另一个BOM需要对它进行再次的展开
通过关联关系将子表中对应的物料id查询出,可再通过关联关系查询出对应物料的用料信息,价格信息
因为每个物料对应的BOM很可能是不一致的所以多级展开无法使用BOM进行查询,此处我使用的是规格型号,可自己再往上加条件
with bb as(
select distinct cc.FItemID from HWbomchild cc
inner join t_ICItem t3 on t3.FItemID=cc.FItemID
where cc.FBOMInterID in(
select
distinct t1.FBOMInterID
from HWbom u1
inner join HWbomchild t1 on u1.FId=t1.FOrgID
inner join t_icitem t2 on t2.FItemID=u1.FItemID
inner join t_ICItem t3 on t3.FItemID=t1.FItemID
left join ICBOM t4 on t4.FInterID=t1.FBOMInterID
left join ICBOMChild t5 on t5.FInterID=t1.FBOMInterID and t5.FEntryID=t1.FEntryID --添加与BOM分组表关联
left join t_SubMessage t6 on t6.FInterID=t4.FBOMSkip
inner join t_SubMessage yy on yy.FInterID=t3.FErpClsID
--left join pp on pp.FNumber=t3.FNumber
where T4.FUseStatus = 1072 and t4.FBomType <> 3 --FBomType;0-普通,1-配置类,2-生产规划类,3-客户BOM,4-特征类
AND t2.FModel='ADW77K')
)
select aa.FItemID,aa.FModel,aa.FName,aa.FNumber,aa.FDeleted,aa.FErpClsID,FUnitID,FUseState,aa.FFullName from bb left join t_ICItem aa on aa.FItemID = bb.FItemID
left join (
select zz.*
from(
SELECT v1.FNumber AS FSupplyNumber,t1.FModel,v1.FName,
u1.FPrice,
t1.FNumber AS FItemNumber,
u1.FLastModifiedDate,
t1.FName AS FItemName, row_number ( ) OVER ( partition BY t1.FNumber,v1.FNumber ORDER BY u1.FLastModifiedDate DESC ) Suquence
FROM t_SupplyEntry u1 INNER JOIN t_Supplier v1 ON u1.FSupID=v1.FItemID
INNER JOIN t_Supply u2 ON u1.FSupID = u2.FSupID AND u1.FItemID=u2.FItemID AND u1.FPType=u2.FPType
INNER JOIN t_ICItem t1 ON u2.FItemID = t1.FItemID
INNER JOIN t_MeasureUnit t2 ON u1.FUnitID = t2.FItemID
INNER JOIN t_Currency t3 ON u1.FCyID = t3.FCurrencyID
INNER JOIN t_Currency u3 ON u3.FCurrencyID = u2.FCurrencyID
LEFT JOIN ICSupOperation t7 on u1.FEntryID=t7.FID
LEFT JOIN t_item t5 ON t1.FParentID=t5.FItemID
LEFT JOIN t_User U ON u1.FLastModifiedBy = U.FUserID
LEFT JOIN t_SubMessage t8 ON t7.FOpID=t8.FInterID
LEFT JOIN t_User uu ON uu.FUserID <> 0 AND u1.FCheckerID = uu.FUserID
WHERE v1.FStatus<>1074 and u1.FPType = '1'
)zz
where zz.Suquence=1
)pp on aa.FNumber=pp.FItemNumber