生产BoM爆炸钻通过幻影BoM

时间:2016-08-02 15:30:51

标签: sql sql-server database recursive-query

这是我的第一篇文章,尽管到目前为止Stack Overflow已经帮助了很多次。希望这次会是一样的。

我尝试使用在线找到的源代码和代码构建定期查询和UDF,但没有运气。变得越来越困惑。

我有什么:

  • 项目表 - 包含项目号和BoM否
  • BoMLines表 - 包含Bom No和所有子项目否或幻像BoM No's



我在追求的是什么:

基本上我需要列出所有以及所有子项数量。 一切似乎都没问题,直到我发现我们还有幻影BoM(Bom称其他BoMs),那些必须'钻进'到物品等级。



预期结果: Screenshot

这是包含BoM爆炸到下一个项目的所有项目列表的表格!



为了更清楚地显示我在使用DDL后的内容:

-- Drop table Items if exist
IF OBJECT_ID('test.Items') IS NOT NULL
    DROP TABLE test.Items;

-- Create Items table
CREATE TABLE test.Items (
  ItemID varchar(30) COLLATE Latin1_General_CI_AS NOT NULL,
  Description varchar(100) COLLATE Latin1_General_CI_AS NOT NULL,
  Prod_BOM_No varchar(30) COLLATE Latin1_General_CI_AS NULL,
  PRIMARY KEY CLUSTERED (ItemID)
    WITH (
      PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF,
      ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
ON [PRIMARY]

-- Drop table BOMLines if exist
IF OBJECT_ID('test.BOMLines') IS NOT NULL
    DROP TABLE test.BOMLines;

-- Create BOMLines table
CREATE TABLE test.BOMLines (
  AutoID int IDENTITY(1, 1) NOT NULL,
  Prod_BOM_No varchar(30) COLLATE Latin1_General_CI_AS NOT NULL,
  Type tinyint DEFAULT 1 NOT NULL,
  No_ varchar(30) COLLATE Latin1_General_CI_AS NOT NULL,
  Qty_Per decimal(18, 8) DEFAULT 1.5 NULL,
  PRIMARY KEY CLUSTERED (AutoID)
    WITH (
      PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF,
      ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
ON [PRIMARY]

还有DML显示我正在处理的数据示例:

--Insert Test Items to Items table
INSERT INTO 
  test.Items
(ItemID, Description, Prod_BOM_No) 
VALUES 
('I1001', 'Item I1001', 'BM1010'), ('I1002', 'Item I1002', 'BM1020'), ('I1003', 'Item I1003', 'BM1030'), 
('I1004', 'Item I1004', 'BM1040'), ('I1005', 'Item I1005', 'BM1050'), ('I1006', 'Item I1006', 'BM1060'), 
('I1007', 'Item I1007', 'BM1070'), ('I1008', 'Item I1008', 'BM1080'), ('I1009', 'Item I1009', 'BM1090'), 
('I1010', 'Item I1010', 'BM1100'), ('I5001', 'Item I5001', ''), ('I5002', 'Item I5002', ''), 
('I5003', 'Item I5003', ''), ('I5004', 'Item I5004', ''), ('I5005', 'Item I5005', ''), 
('I5006', 'Item I5006', ''), ('I5007', 'Item I5007', ''), ('I5008', 'Item I5008', ''), 
('I5009', 'Item I5009', ''), ('I5010', 'Item I5010', ''), ('I5011', 'Item I5011', ''), 
('I5012', 'Item I5012', ''), ('I5013', 'Item I5013', ''), ('I5014', 'Item I5014', ''), 
('I5015', 'Item I5015', ''), ('I5016', 'Item I5016', ''), ('I5017', 'Item I5017', ''), 
('I5018', 'Item I5018', ''), ('I5019', 'Item I5019', ''), ('I5020', 'Item I5020', '');

-- Insert test BOMs to BOMLines table
INSERT INTO 
  test.BOMLines
( Prod_BOM_No, No_, [Type])
VALUES 
('BM1010', 'I5001', 1), ('BM1020', 'I5002', 1), ('BM1020', 'I5003', 1), 
('BM1030', 'BM1031', 2), ('BM1030', 'I5004', 1), ('BM1031', 'I5005', 1), 
('BM1040', 'I5006', 1), ('BM1050', 'I5007', 1), ('BM1050', 'BM1051', 2), 
('BM1051', 'BM1052', 2), ('BM1052', 'I5008', 1), ('BM1060', 'I5009', 1), 
('BM1060', 'I5010', 1), ('BM1060', 'I5011', 1), ('BM1060', 'BM1061', 2), 
('BM1061', 'I5012', 1), ('BM1061', 'I5013', 1), ('BM1061', 'BM1062', 2), 
('BM1062', 'I5013', 1), ('BM1062', 'I5014', 1), ('BM1070', 'I5015', 1), 
('BM1080', 'I5016', 1), ('BM1080', 'I5017', 1), ('BM1080', 'I5018', 1), 
('BM1090', 'I5019', 1), ('BM1100', 'I5020', 1);

1 个答案:

答案 0 :(得分:3)

您可以使用Recursive Common Table Expression

;With BOMs (Prod_BOM_No, Type, No_, Qty_Per) AS
(
    select Prod_BOM_No, Type, No_, Qty_Per
    from test.BOMLines
    union all
    select test.BOMLines.Prod_BOM_No, BOMs.Type, BOMs.No_, convert(decimal(18, 8), test.BOMLines.Qty_Per * BOMs.Qty_Per) as Qty_Per
    from test.BOMLines
    join BOMs 
    on test.BOMLines.Type = 2 and test.BOMLines.No_ = BOMs.Prod_BOM_No
)
select ItemID, Description, No_, Qty_Per
from test.Items
join BOMs
on test.Items.Prod_BOM_No = BOMs.Prod_BOM_No
    and Type = 1
order by 1, 2