大佬您好,从咱们这个描述中,这种结构本质上是一个 有向无环图(DAG),而不是简单的树形结构,主要是同一个子BOM可以被多个父级半成品引用。
这个的数据存储,也可以在关系型数据库中存储,但是存储的方式,不再是id和pid的方式,而是需要两张表组合,查询也需要递归的方式。
1、物料信息表,记录所以的物料信息,没有物料之间的关系,比如下面的数据表
创建SQL如下:
- CREATE TABLE materials (
- material_id VARCHAR(50) PRIMARY KEY, -- 物料编码
- name VARCHAR(255) NOT NULL,
- type ENUM('raw', 'semi', 'finished') NOT NULL, -- 原材料/半成品/成品
- unit VARCHAR(20),
- version VARCHAR(20) DEFAULT '1.0' -- 支持版本控制(可选)
- );
复制代码
2、物料信息关系图,这个表中,无论是子BOM,还是父BOM,都可以被多次引用
创建SQL如下:
- CREATE TABLE bom_items (
- id BIGINT AUTO_INCREMENT PRIMARY KEY,
- parent_id VARCHAR(50) NOT NULL, -- 父物料ID(半成品或成品)
- child_id VARCHAR(50) NOT NULL, -- 子物料ID(可以是原材料或另一个半成品)
- quantity DECIMAL(18,6) NOT NULL DEFAULT 1.0,
- unit VARCHAR(20),
- effective_date DATE, -- 生效日期(用于版本/时间维度)
- obsolete_date DATE, -- 失效日期(可选)
- FOREIGN KEY (parent_id) REFERENCES materials(material_id),
- FOREIGN KEY (child_id) REFERENCES materials(material_id),
- UNIQUE KEY uk_parent_child_active (parent_id, child_id, effective_date)
- );
复制代码
最终的查询需要递归的方式,测试SQL如下:
- WITH RECURSIVE bom_tree AS (
- -- 锚点:从顶层成品开始
- SELECT
- parent_id,
- child_id,
- quantity,
- 1 AS level
- FROM bom_items
- WHERE parent_id = '1' -- 指定成品编码
- UNION ALL
- -- 递归:展开子项(如果子项本身也是半成品)
- SELECT
- bi.parent_id,
- bi.child_id,
- bi.quantity * bt.quantity AS quantity, -- 累计用量(可选)
- bt.level + 1
- FROM bom_items bi
- INNER JOIN bom_tree bt ON bi.parent_id = bt.child_id
- )
- SELECT * FROM bom_tree;
复制代码
测试结果如下:
|