求BOM根据阶数展开的SQL语句

本文介绍了一种在SQL Server环境中实现物料清单(BOM)多级展开查询的方法。通过使用递归查询和函数来处理复杂的BOM层级关系,实现了根据指定编码和阶数返回相应子件及其用量的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我有一小型 ERP 系统,产品BOM 定义好了,可查询问题出来了
系统中没有相应的查询功能,随想 通过 查询分析器 自行写 sql 查询语句,然后导入系统中

可苦于自己sql水平有限,而这个又复杂,不能成功,
请大家不吝赐教,先行谢过

BOM表结构:(编码为虚拟出的编码,实际编码父子关系是一样的,编码定义规则与此不同)
父件编码  子件编码  用量
a          a.1      2
a          a.2      1
a          a.3      2
a.1        a.1.1    3
a.1        a.1.2    4
a.1        a.1.3    2
a.2        a.2.1    2
a.2        a.2.2    2
a.1.1      a.1.1.1  1
a.1.1      a.1.1.2  2

要求根据录入的条件:(编码,阶数)展开:

例如录入(a,1)展开
编码    用量
a.1      2
a.2      1
a.3      2
录入(a,2)展开
编码    用量
a.1.1    2*3
a.1.2    2*4
a.1.3    2*2
a.2.1    1*2
a.2.2    1*2
a.3      2

录入(a,3)展开
编码    用量
a.1.1.1  2*3*1
a.1.1.2  2*3*2
a.1.2    2*4
a.1.3    2*2
a.2.1    1*2
a.2.2    1*2
a.3      2

 

-----------------------------------------------

--SQL2005

--> 生成测试数据表:bom

If not object_id('[bom]') is null
   
Drop table [bom]
Go
Create table [bom]([父件编码] nvarchar(5),[子件编码] nvarchar(7),[用量] int)
Insert bom
Select 'a','a.1',2 union all
Select 'a','a.2',1 union all
Select 'a','a.3',2 union all
Select 'a.1','a.1.1',3 union all
Select 'a.1','a.1.2',4 union all
Select 'a.1','a.1.3',2 union all
Select 'a.2','a.2.1',2 union all
Select 'a.2','a.2.2',2 union all
Select 'a.1.1','a.1.1.1',1 union all
Select 'a.1.1','a.1.1.2',2
Go
--Select * from bom
If not object_id('f_getbom') is null
   
Drop function f_getbom
Go
create function f_getbom(@No varchar(10),@lvl int)
returns table
as
return
with t as
(
 
select *,1 lvl from bom where 父件编码=@No
 
union all
 
select a.父件编码,a.子件编码,a.用量*b.用量,b.lvl+1 from bom a,t b where a.父件编码=b.子件编码
)
select 子件编码 as 编码,用量
from t a
where lvl<=@lvl
   
and not exists(
       
select 1
       
from t
       
where lvl<=@lvl
           
and a.子件编码=父件编码)
go

select * from f_getbom('a',3)
/*
编码      用量
------- -----------
a.3     2
a.2.1   2
a.2.2   2
a.1.2   8
a.1.3   4
a.1.1.1 6
a.1.1.2 12

(7 行受影响)
*/
select * from f_getbom('a',2)
/*
编码      用量
------- -----------
a.3     2
a.2.1   2
a.2.2   2
a.1.1   6
a.1.2   8
a.1.3   4

(6 行受影响)
*/
select * from f_getbom('a',1)
/*
编码      用量
------- -----------
a.1     2
a.2     1
a.3     2

(3 行受影响)
*/
-------------------------------------------------

SQL2000:

 

--> 生成测试数据表:bom

If not object_id('[bom]') is null
   
Drop table [bom]
Go
Create table [bom]([父件编码] nvarchar(5),[子件编码] nvarchar(7),[用量] int)
Insert bom
Select 'a','a.1',2 union all
Select 'a','a.2',1 union all
Select 'a','a.3',2 union all
Select 'a.1','a.1.1',3 union all
Select 'a.1','a.1.2',4 union all
Select 'a.1','a.1.3',2 union all
Select 'a.2','a.2.1',2 union all
Select 'a.2','a.2.2',2 union all
Select 'a.1.1','a.1.1.1',1 union all
Select 'a.1.1','a.1.1.2',2
Go
--Select * from bom
--
>SQL查询如下:
--
创建函数1
If not object_id('f_getbom1') is null
   
Drop function f_getbom1
Go
create function f_getbom1(@No varchar(10))
returns @t table(父件编码 varchar(10),子件编码 varchar(10),用量 int,lvl int)
as
begin
   
declare @i int
   
set @i=1
   
insert @t select *,@i from bom where 父件编码=@No
   
while @@rowcount>0
       
begin
           
set @i = @i + 1       
           
insert @t
           
select a.父件编码,a.子件编码,a.用量*b.用量,@i
           
from bom a,@t b
           
where a.[父件编码]=b.[子件编码]
             
and b.lvl=@i-1
       
end
   
return
end
go
--创建函数2
If not object_id('f_getbom2') is null
   
Drop function f_getbom2
Go
create function f_getbom2(@No varchar(10),@lvl int)
returns table
as
return(
   
select 子件编码 as 编码,用量
   
from f_getbom1(@No) a
   
where lvl<=@lvl
       
and not exists(
           
select 1
           
from f_getbom1(@No)
           
where lvl<=@lvl
               
and a.子件编码=父件编码)
)
go
--调用查询
select * from f_getbom2('a',1)
/*
编码         用量
---------- -----------
a.1        2
a.2        1
a.3        2

(3 行受影响)
*/
select * from f_getbom2('a',2)
/*
编码         用量
---------- -----------
a.3        2
a.1.1      6
a.1.2      8
a.1.3      4
a.2.1      2
a.2.2      2

(6 行受影响)
*/
select * from f_getbom2('a',3)
/*
编码         用量
---------- -----------
a.3        2
a.1.2      8
a.1.3      4
a.2.1      2
a.2.2      2
a.1.1.1    6
a.1.1.2    12

(7 行受影响)
*/
--------------------

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值