在sqlalchemy中外部连接两个表时按问题排序

时间:2014-10-08 09:13:09

标签: python join flask sqlalchemy

我是一个尝试使用sqlalchemy烧瓶的菜鸟,并且我从一个基本查询中排序问题。

我有一个父表和两个加入多对多关联表:

class Product(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    (...)
    qty_stock = db.Column(db.Integer)
    requested_products = db.relationship('RequestedProducts')
    ordered_products = db.relationship('OrderedProducts')

class OrderedProducts(db.Model):
    __tablename__ = 'orderedproducts'
    order_id = db.Column(db.Integer, db.ForeignKey('order.id'), primary_key=True)
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'), primary_key=True)
    quantity = db.Column(db.Integer, default=1)
    qty_delivered = db.Column(db.Integer, default=0)
    product = db.relationship('Product', backref='order_assocs')

class RequestedProducts(db.Model):
    __tablename__ = 'requestedproducts'
    request_id = db.Column(db.Integer, db.ForeignKey('request.id'), primary_key=True)
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'), primary_key=True)
    quantity = db.Column(db.Integer, default=1)
    qty_supplied = db.Column(db.Integer, default=0)
    product = db.relationship('Product', backref='request_assocs')

在我的视图类中,每个产品有4个表格列,显示库存数量,请求产品数量,订购产品数量和净库存量,基本上(库存数量 - 请求+订购)。这是我试图开始工作的净股票价值的查询:

products = Product.query.filter_by(active_flg=True)
    .filter_by(category_id=int(g.category_id))
    .outerjoin(Product.requested_products)
    .outerjoin(Product.ordered_products)
    .group_by(Product.id)
#Count requested amount for each product
reqs = func.coalesce((func.sum(RequestedProducts.quantity) - func.sum(RequestedProducts.qty_supplied)), 0)
#Count ordered amount for each product
ords = func.coalesce((func.sum(OrderedProducts.quantity) - func.sum(OrderedProducts.qty_delivered)), 0)
result = (Product.qty_stock - reqs + ords)
products = products.order_by(result.desc())

现在,函数按预期工作,唯一的问题是order_by函数 - 订单被扰乱。我发现原因可能在双外连接中。有没有人知道如何处理?

另外,我真的是sqlalchemy和flask的初学者,所以我非常感谢任何建议或更好的解决方案(可执行的技能有限)。谢谢!

1 个答案:

答案 0 :(得分:2)

如果您已经将混合属性用于部分和,那么将它们组合在一起应该非常容易。

class Product(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    qty_stock = db.Column(db.Integer)
    requested_products = db.relationship('RequestedProducts')
    ordered_products = db.relationship('OrderedProducts')

    @hybrid_property
    def diff_orders(self):
        return sum(op.quantity - op.qty_delivered
                   for op in self.ordered_products)

    @diff_orders.expression
    def diff_orders(cls):
        return (db.select([db.func.coalesce(
            db.func.sum(
                db.func.coalesce(
                    OrderedProducts.quantity - OrderedProducts.qty_delivered, 0)
            ), 0)])
            .where(OrderedProducts.product_id == cls.id)
            .label("diff_orders")
        )

    @hybrid_property
    def diff_requests(self):
        return sum(op.quantity - op.qty_supplied
                   for op in self.requested_products)

    @diff_requests.expression
    def diff_requests(cls):
        return (db.select([db.func.coalesce(
            db.func.sum(
                db.func.coalesce(
                    RequestedProducts.quantity - RequestedProducts.qty_supplied, 0)
            ), 0)])
            .where(RequestedProducts.product_id == cls.id)
            .label("diff_requests")
        )

在哪种情况下,使用可以类似于:

products = db.session.query(
    Product,
    # Product.diff_orders,
    # Product.diff_requests,
    # Product.qty_stock + Product.diff_requests - Product.diff_orders,
).order_by((Product.qty_stock + Product.diff_requests - Product.diff_orders).desc())
for x in products:
    print(x)