我继承了库存管理系统。它使用python 3,flask和sqlalchemy。该系统包含零件和产品。产品具有物料清单(BOM)。 BOM由线组成,每条线可以是零件或另一产品。它们对嵌套产品的数量没有限制。 BOM行由下面的多态模型表示。
class ProductLine(db.Model):
__tablename__ = 'ProductLineItems'
id = db.Column('RowID', db.Integer, primary_key=True)
product_id = db.Column('ProductID', db.Integer, db.ForeignKey(Product.id))
qty = db.Column('ComponentQuantity', db.Float)
is_subassembly = db.Column('IsSubAssembly', db.Boolean)
product = db.relationship('Product', backref='bom_items', primaryjoin="(ProductLine.product_id==Product.id)")
__mapper_args__ = {
'polymorphic_on': is_subassembly,
}
class ProductPart(ProductLine):
__mapper_args__ = {'polymorphic_identity': False}
part_id = db.Column('ComponentID', db.Integer, db.ForeignKey(Part.id))
part = db.relationship('Part', backref='part_boms', primaryjoin="(ProductPart.part_id==Part.id)")
@property
def primary_vendor_cost(self):
@property
def alternate_vendor_cost(self):
@property
def is_subproduct(self):
def contains_subproduct(self, subproduct):
@validates('part_id')
def validate_part_id(self, key, part_id):
class ProductSubproduct(ProductLine):
__mapper_args__ = {'polymorphic_identity': True}
subproduct_id = db.Column('SubAssemblyProductID', db.Integer, db.ForeignKey(Product.id))
part = db.relationship('Product', backref='subproduct_boms',
primaryjoin="(ProductSubproduct.subproduct_id==Product.id)")
@property
def primary_vendor_cost(self):
@property
def alternate_vendor_cost(self):
@property
def is_subproduct(self):
def contains_subproduct(self, subproduct):
@validates('subproduct_id')
def validate_subproduct_id(self, key, subproduct_id):
当前要查找产品中的所有零件,我正在使用python遍历每个BOM表行,并检查BOM表项是零件还是产品。如果是产品,那么我再次循环查找所有零件。
def flattened_bom(self, bom_dict, qty=1):
for item in self.bom_items:
required_qty = item.qty * qty
if item.is_subassembly:
item.part.flattened_bom(qty=required_qty, bom_dict=bom_dict)
else:
empty_tuple = (item.part, 0)
bom_dict[item.part.id] = (item.part, bom_dict.get(item.part.id, empty_tuple)[1] + required_qty)
return bom_dict
这有效,但是速度很慢。我想知道他们是否是使用sqlalchemy orm或raw sql通过查询获得BOM表的所有部分的方法
答案 0 :(得分:2)
我按照建议研究了递归CTE,并浏览了这两页,这有助于我进入下面的解决方案,该解决方案适用于Recursive CTE's Explained和IBM Recursion Example
WITH cte_bom(ComponentID, ComponentQuantity, SubAssID) AS (
SELECT Root.ComponentID, Root.ComponentQuantity, Root.SubAssemblyProductID
FROM ProductLineItems AS Root
WHERE Root.ProductID = ?
UNION ALL
SELECT Child.ComponentID, (Child.ComponentQuantity * Parent.ComponentQuantity), Child.SubAssemblyProductID
FROM ProductLineItems AS Child, cte_bom AS Parent
WHERE Parent.SubAssID = Child.ProductID
)
SELECT BOM.ComponentID, C.ComponentName, SUM(BOM.ComponentQuantity) AS Qty
FROM cte_bom AS BOM
INNER JOIN ComponentInventory C ON BOM.ComponentID = C.ComponentID
WHERE BOM.ComponentID NOT NULL
GROUP BY BOM.ComponentID