计算BOM的物料需求量

东莞寻香苑 2011-07-25 11:33:48

...全文
1540 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
东莞寻香苑 2011-07-31
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 liushaoyi0704 的回复:]
看了前几楼决定先来回复个与问题无关的帖子:
LZ提问的态度实在不敢恭维,人家有可能只是没理解透你的需求,至少人家也是用心在回答你的问题,而且还找了资料。即使不是你需要的,你也应该礼貌指出,怎能出言冲撞?
[/Quote]
不好意思,是我对那个人太气了!
每次看到他回复都气(不仅仅是在我的贴上),经常看到他在别人贴上回复时,一开始又不说什么,等别人回复了,他就在别人的基础上修改,然后评别人回复,说别的这了那了的,很不爽!
东莞寻香苑 2011-07-31
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 gaowei_cool 的回复:]
计算BOM的需求量,提供BOM的需求量,在线结存(也有替代品),算出最后的差额。这个用函数做会简单些,最后返回数据。
CREATE FUNCTION [dbo].[f_mesbomcount] (
@vc_remark varchar(200), --机种
@vc_invcode varchar(30), --物料编号
@in_level int, --层级
@dc_dqty decim……
[/Quote]
你太神了,机种好像我没有说,我的里面确实有机种!!
kong佳 2011-07-29
  • 打赏
  • 举报
回复
也许把BOM分成几个表,然后通过成品号(A)进行内联,这样对物料的分解可能更详细,也更简单。只是在运算时对资源的损耗可能会更大一点。三楼其实说得也没错,完全可以用视图的方法来进行数据提取。
gaowei_cool 2011-07-28
  • 打赏
  • 举报
回复
计算BOM的需求量,提供BOM的需求量,在线结存(也有替代品),算出最后的差额。这个用函数做会简单些,最后返回数据。
CREATE FUNCTION [dbo].[f_mesbomcount] (
@vc_remark varchar(200), --机种
@vc_invcode varchar(30), --物料编号
@in_level int, --层级
@dc_dqty decimal(15,4) --需求量
)
RETURNS @gt_bomcount TABLE(
remark varchar(200),
invcode varchar(30),
level int,
dqty decimal(15,4),
dc_sqty decimal(15,4),
dc_balance decimal(15,4)
)
AS
begin
Declare @gt_bomshare TABLE (vc_bomid varchar(200),
vc_version varchar(30),
vc_parentbomid varchar(200),
in_level int--层级,输入
)

Declare @vc_parentVersion varchar(30)
Declare @vc_parentbomid varchar(30)
Declare @vc_version varchar(30)
Declare @flag bit
Declare @l int

Set @flag = 1

--SELECT DISTINCT @vc_remark=vc_remark FROM gt_mesprocesscount WHERE vc_remark LIKE '%'+@vc_remark+'%'
SELECT @vc_remark=vc_invcode FROM gt_inventory WHERE vc_invcode LIKE '%'+@vc_remark+'%'

Insert into @gt_bomShare(vc_bomid,vc_version,vc_parentbomid,in_level)
Select vc_bomid,vc_version,vc_parentbomid,1 from gt_bom
where vc_version in (select vc_version from gt_bom where vc_bomid=@vc_remark)
and ((@vc_invcode != '99' And vc_bomid = @vc_invcode)
Or (@vc_invcode = '99' And vc_bomid in (select vc_version from gt_bom where vc_bomid=@vc_remark) ))


Set @l = 1
While @flag = 1
Begin
set @flag = 0
Declare c cursor for --定义游标cursor1
Select vc_bomid,vc_version from @gt_bomShare
Where in_level = @l group by vc_bomid,vc_version --使用游标的对象(跟据需要填入select文)

Open c --打开游标
Fetch next from c into @vc_parentbomid,@vc_version --将游标向下移1行,获取的数据放入之前定义的变量vc_version中
Set @l = @l+1
While @@fetch_status=0 --判断是否成功获取数据
Begin
set @flag = 1
insert into @gt_bomShare(vc_bomid,vc_version,vc_parentbomid,in_level)
select vc_bomid,vc_version,vc_parentbomid,@l from gt_bom
Where vc_version in (select vc_version from gt_bom where vc_bomid=@vc_remark)
and ((@vc_parentbomid != '99' And vc_parentbomid = @vc_parentbomid)
Or (@vc_parentbomid = '99' And vc_parentbomid in (select vc_version from gt_bom where vc_bomid=@vc_remark) ))

insert into @gt_bomShare(vc_bomid,vc_version,vc_parentbomid,in_level)
select vc_sharebomid,vc_shareversion,@vc_parentbomid,@l from gt_bomshare where vc_bomid in
(select vc_bomid from gt_bom Where vc_parentbomid = @vc_parentbomid and vc_parentversion in (select vc_version from gt_bom where vc_bomid=@vc_remark) group by vc_bomid)
and vc_version in
(select vc_version from gt_bom Where vc_parentbomid = @vc_parentbomid and vc_parentversion in (select vc_version from gt_bom where vc_bomid=@vc_remark) group by vc_version)

Fetch next from c into @vc_parentbomid,@vc_version --将游标向下移1行

End
close c --关闭游标
deallocate c
End

Declare @dc_sqty decimal(15,4)
Declare @dc_balance decimal(15,4)
Declare @balance decimal(15,4)
Declare @invcode varchar(30)
Declare @isflag bit
Set @isflag = 1

Select @dc_sqty=sum(Isnull(dc_sqty,0)) From gt_mesprocesscount
Where vc_remark Like '%' + @vc_remark + '%' And vc_invcode = @vc_invcode

Select @dc_balance=@dc_sqty-@dc_dqty

Insert into @gt_bomcount values(@vc_remark,@vc_invcode,1,@dc_dqty,@dc_sqty,@dc_balance)

Declare @levle int
Set @levle =1
While @isflag = 1
Begin
set @isflag = 0
Declare cursor1 cursor for --定义游标cursor1
Select invcode,dc_balance from @gt_bomCount where level = @levle --使用游标的对象(跟据需要填入select文)

Open cursor1 --打开游标
Fetch next from cursor1 into @invcode,@balance --将游标向下移1行,获取的数据放入之前定义的变量vc_version中

While @@fetch_status=0 --判断是否成功获取数据
Begin
set @isflag = 1
set @levle = @levle+1
Declare @vc_bomid varchar(30),@il int

Declare c2 cursor for
select vc_bomid from @gt_bomShare where in_level = @levle group by vc_bomid

open c2
Fetch next from c2 into @vc_bomid
While @@fetch_status=0
Begin
if @balance>0
Begin
insert into @gt_bomCount(remark,invcode,level,dqty,dc_sqty,dc_balance)
Select @vc_remark,vc_invcode,@levle,@balance,sum(Isnull(dc_sqty,0)),sum(isnull(dc_sqty,0))-@balance
From gt_mesprocesscount Where vc_invcode = @vc_bomid and (vc_bomversion
in(select vc_version from @gt_bomShare where vc_bomid=@vc_bomid group by vc_version))
Group By vc_invcode
End
Else
Begin
insert into @gt_bomCount(remark,invcode,level,dqty,dc_sqty,dc_balance)
Select @vc_remark,vc_invcode,@levle,-@balance,sum(Isnull(dc_sqty,0)),sum(Isnull(dc_sqty,0))+@balance
From gt_mesprocesscount Where vc_invcode = @vc_bomid and (vc_bomversion
in(select vc_version from @gt_bomShare where vc_bomid=@vc_bomid group by vc_version))
Group By vc_invcode
End
Fetch next from c2 into @vc_bomid
End
Close c2
Deallocate c2

Fetch next from cursor1 into @invcode,@balance --将游标向下移1行
End

Close cursor1 --关闭游标
Deallocate cursor1
End

RETURN
End
grart 2011-07-28
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 moneysoft 的回复:]
BOM按照范式被设计成Parent/Child的相对路径表达方式,
虽然微软又增加了CTE递归,简化了sql语句,
但是,还是很难应付各种复杂的统计汇算场合,
而且,也增加了技术依赖;

在尝试了多次项目以后,我最终选择了微软自己采用的解决方案,
就是绝对路径法(ValuePath)描述树形结构,
我认为这大大降低了开发难度,
比如,楼主要统计A的所有清单,
只要统计root=A……
[/Quote]
同意,递归增加了复杂性
qingmingcom 2011-07-27
  • 打赏
  • 举报
回复
这个比较中肯。

[Quote=引用 28 楼 liushaoyi0704 的回复:]

看了前几楼决定先来回复个与问题无关的帖子:
LZ提问的态度实在不敢恭维,人家有可能只是没理解透你的需求,至少人家也是用心在回答你的问题,而且还找了资料。即使不是你需要的,你也应该礼貌指出,怎能出言冲撞?
[/Quote]
化外之民 2011-07-27
  • 打赏
  • 举报
回复
看了前几楼决定先来回复个与问题无关的帖子:
LZ提问的态度实在不敢恭维,人家有可能只是没理解透你的需求,至少人家也是用心在回答你的问题,而且还找了资料。即使不是你需要的,你也应该礼貌指出,怎能出言冲撞?
fsh1985 2011-07-26
  • 打赏
  • 举报
回复
我给个思路


declare @Count bigint
set @Count = 0

declare @LevelInt int
set @LevelInt = 0

if object_id('Tempdb..#A') is not null
drop table #A
create table #A([料号] [Varchar](20),[用量] [numeric](13,6),阶数 int)
insert into #A(料号,用量,阶数)
select 子料号,用量*2000,@LevelInt from [BOM] where 料号='A'

select @Count = COUNT(0) from #A

while @Count > 0
begin


update #A
set 用量=case when A1.用量>A2.数量 then (A1.用量-A2.数量) else A1.用量 end
from #A as A1 left join Stock AS A2 on A1.料号=A2.料号 and A1.用量>A2.数量



insert into #A(料号,用量,阶数)
select A1.子料号,A.用量*A1.用量,@LevelInt from #A as A left join [BOM] as A1 on A.料号=A1.子料号 and A.阶数=@LevelInt

set @LevelInt = @LevelInt + 1

--这边改下,应该就不问题,现在是死循环
if not EXISTS (select * from #A as A left join [BOM] as A1 on A.料号=A1.料号 and A.阶数=@LevelInt )
set @Count=0


end

select * from #A



东莞寻香苑 2011-07-26
  • 打赏
  • 举报
回复
還是沒有實現呢
ruanwei1987 2011-07-26
  • 打赏
  • 举报
回复
--缪军-- 2011-07-26
  • 打赏
  • 举报
回复
BOM按照范式被设计成Parent/Child的相对路径表达方式,
虽然微软又增加了CTE递归,简化了sql语句,
但是,还是很难应付各种复杂的统计汇算场合,
而且,也增加了技术依赖;

在尝试了多次项目以后,我最终选择了微软自己采用的解决方案,
就是绝对路径法(ValuePath)描述树形结构,
我认为这大大降低了开发难度,
比如,楼主要统计A的所有清单,
只要统计root=A.valuepath的所有记录就可以了
东莞寻香苑 2011-07-26
  • 打赏
  • 举报
回复
謝謝大家了,晚上,我試試就結
东莞寻香苑 2011-07-25
  • 打赏
  • 举报
回复
上阶库存数量够了,就不分解下阶了,如果没有或不够就分解下阶,算出最后所需即可
ruanwei1987 2011-07-25
  • 打赏
  • 举报
回复
原材料指的是 B C1 C21 C22,D1,D2 E1,E2,E3???
东莞寻香苑 2011-07-25
  • 打赏
  • 举报
回复
--Bom
CREATE TABLE [BOM] ([料号] [Varchar](20),[子料号] [Varchar](20),[用量] [numeric](13,6),[损耗率] [numeric](5,2))
INSERT INTO [BOM]
SELECT 'A','A',1,0 union all
SELECT 'A','B',1,0.01 union all
SELECT 'A','C',1,0 UNION ALL
SELECT 'A','D',1,0 UNION ALL
SELECT 'A','E',1,0 UNION ALL
SELECT 'C','C1',1,0 UNION ALL
SELECT 'C','C2',2,0 UNION ALL
SELECT 'D','D1',1,0 UNION ALL
SELECT 'D','D2',1,0 UNION ALL
SELECT 'E','E1',0.09,0 UNION ALL
SELECT 'E','E2',0.09,0 UNION ALL
SELECT 'E','E3',0.01,0 UNION ALL
SELECT 'C2','C21',1,0 UNION ALL
SELECT 'C2','C22',1,0

--现有库存
create TABLE [Stock]([料号] [Varchar](20),[数量] [numeric](13,6))
INSERT INTO [Stock]
select 'A',300 union all
select 'C2',200 union all
select 'E2',800 union all
select 'D',10000


现在要生产10000个A,需要购买多少原料?
doubleu2005 2011-07-25
  • 打赏
  • 举报
回复
你这是做什么的BOM这么繁琐,我的天
东莞寻香苑 2011-07-25
  • 打赏
  • 举报
回复
可能是我這邊數據庫的問題 無法繫結多重部份 (Multi-Part) 識別碼 "n.料号"。
老冯 2011-07-25
  • 打赏
  • 举报
回复
如果是这个,你转换一下类型就可以了。我做测试的时候,是“用量”的类型改为INT, 你原来是nemeric(13,6). 你这样改一下



With BOM_CTE
As
(
Select 生产的工料 = 料号 ,
料号,
子料号,
用量 = 用量,
生产用量 = 用量
From BOM
Where 料号 = 'A' And 子料号 != 'A'

Union All

Select c.生产的工料,
n.料号,
n.子料号,
n.用量 ,
--n.用量*c.生产用量
Cast(n.用量*c.生产用量 As Numeric(13, 6))
From BOM N

Inner Join BOM_CTE C

On C.子料号 = N.料号
)

Select 生产的工料,
料号,
子料号,
用量 = 用量,
生产用量 = Sum(生产用量)
From BOM_CTE
Group By 生产的工料,
料号,
子料号,
用量

老冯 2011-07-25
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 csui2008 的回复:]
引用 17 楼 sanmaotuo 的回复:
运行结果

SQL code



A A B 1000 1000
A A C 1000 1000
A A D 1000 1000
A A E 1000 1000
A C C1 1000 1000
A C C2 2000 2000
……

我這里好像運行不了
[/Quote]

是什么错误呢? 是不是这个 “消息 240,级别 16,状态 1,第 2 行
在递归查询 "BOM_CTE" 的列 "生产用量" 中,定位点类型和递归部分的类型不匹配。”
东莞寻香苑 2011-07-25
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 sanmaotuo 的回复:]
运行结果

SQL code



A A B 1000 1000
A A C 1000 1000
A A D 1000 1000
A A E 1000 1000
A C C1 1000 1000
A C C2 2000 2000
……
[/Quote]
我這里好像運行不了
加载更多回复(14)
物料需求计划(简称为MRP)与主生产计划一样属于ERP计划管理体系,它主要解决企业生产中的物料需求与供给之间的关系,即无论是对独立需求的物料,还是相关需求的物料物料需求计划都要解决“需求什么?现有什么?还缺什么?什么时候需要?”等几个问题。它是一个时段优先计划系统,其主要对象是决定制造与采购的净需求计划。它是由主生产计划推动运行的,但反过来,它又是主生产计划的具体化和实现主生产计划的保证计划。     由于物料需求计划是把主生产计划排产的产品分解为各个零部件的生产计划和采购件的采购计划,因此,制订物料需求计划前就必须具备以下的基本数据:第一项数据是主生产计划,它指明在某一计划时间段内应生产出的各种产品和备件,它是物料需求计划制订的一个最重要的数据来源。第二项数据是物料清单(BOM),它指明了物料之间的结构关系,以及每种物料需求的数量,它是物料需求计划系统中最为基础的数据。第三项数据是库存记录,它把每个物料品目的现有库存量和计划接受量的实际状态反映出来。第四项数据是提前期,决定着每种物料何时开工、何时完工。应该说,这四项数据都是至关重要、缺一不可的。缺少其中任何一项或任何一项中的数据不完整,物料需求计划的制订都将是不准确的。因此,在制订物料需求计划之前,这四项数据都必须先完整地建立好,而且保证是绝对可靠的、可执行的数据。     一般来说,物料需求计划的制订是遵照先通过主生产计划导出有关物料需求量与需求时间,然后,再根据物料的提前期确定投产或订货时间的计算思路。其基本计算步骤如下:1.计算物料的毛需求量。即根据主生产计划、物料清单得到第一层级物料品目的毛需求量,再通过第一层级物料品目计算出下一层级物料品目的毛需求量,依次一直往下展开计算,直到最低层级原材料毛坯或采购件为止。     2.净需求量计算。即根据毛需求量、可用库存量、已分配量等计算出每种物料的净需求量,即净需求量=毛需求量+已分配量-可用库存量-在途量。     3.批量计算。即由相关计划人员对物料生产作出批量策略决定,不管采用何种批量规则或不采用批量规则,净需求量计算后都应该表明有否批量要求。     4.安全库存量、废品率和损耗率等的计算。即由相关计划人员来规划是否要对每个物料的净需求量作这三项计算。     5.下达计划订单。即指通过以上计算后,根据提前期生成计划订单。物料需求计划所生成的计划订单,要通过能力资源平衡确认后,才能开始正式下达计划订单。     6.再一次计算物料需求计划的再次生成大致有两种方式第一种方式会对库存信息重新计算,同时覆盖原来计算的数据,生成的是全新的物料需求计划;第二种方式则只是在制定、生成物料需求计划的条件发生变化时,才相应地更新物料需求计划有关部分的记录。这两种生成方式都有实际应用的案例,至于选择哪一种要看企业实际的条件和状况。
下载代码方式:https://pan.quark.cn/s/e474201115cd 物料需求计划(通常简称为MRP)与主生产计划一样,同属于企业资源计划(ERP)的规划体系范畴。它主要针对企业生产过程中物料需求与供给之间的平衡关系进行管理,无论是对独立需求的物料,还是对相关需求的物料物料需求计划都需要明确“需要哪些物料?当前具备哪些物料?还缺少哪些物料?何时需要这些物料?”等核心问题。它本质上是一个基于时间优先级的计划系统,其核心关注点是确定制造与采购活动的净需求计划。物料需求计划由主生产计划所驱动,同时它又是主生产计划的具体体现,并作为确保主生产计划得以实现的保障性计划。由于物料需求计划是将主生产计划排产的产品分解为各个零部件的生产计划以及采购件的采购计划,因此在制定物料需求计划之前,必须准备好以下几项基础数据:首要数据是主生产计划,它详细说明了在特定计划周期内需要生产出的各类产品和备件,是制定物料需求计划最关键的依据。其次是物料清单(BOM),它明确了物料之间的层级结构关系,以及每种物料的具体需求量,是物料需求计划系统中最基础的数据组成部分。再次是库存记录,它反映了每个物料品目的当前库存量与计划接收量的实际状况。最后是提前期,它决定了每种物料何时开始生产以及何时完成生产。这四项数据均至关重要,缺一不可。倘若其中任何一项或任何一项中的数据存在缺失或不完整,物料需求计划的制定都将失去准确性。因此,在着手制定物料需求计划之前,这四项数据必须首先完整建立,并且确保它们是绝对可靠且可执行的。通常情况下,物料需求计划的制定遵循先通过主生产计划导出物料需求量与需求时间的流程,随后再依据物料的提前期来确定投产或订货时间的计算逻辑。其基本计算步骤如下:1.计算物料的毛需...

111,125

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧