2014-10-08 2 views
1

Я noob пытается использовать колбу с 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 и флягой, поэтому я был бы очень благодарен за любой совет или лучшее решение (исполняемый с моими ограниченными навыками). Спасибо!

+0

какую базу данных вы используете? – van

+0

Sqlite для разработки, MySQL на сервере. Проблема сортировки возникает на обоих. – Hinek

+0

Странно, я скопировал ваш код, и он отлично работает на 'sqlite'. В этой заметке: вы также не хотите видеть частичные суммы в своих представлениях ('reqs',' ords' и 'result')? – van

ответ

2

Если вы уже используете Hybrid Attributes для частичных сумм, то их должно быть довольно легко объединить.

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) 
+0

Это сработало! Я все еще изучаю основы, поэтому я понятия не имел, что вы можете определить эти выражения в классе модели. Ваше объяснение и терпение были чрезвычайно полезны! Огромное спасибо!! – Hinek

+0

Что делает coalesce? Я так смущен, почему это работает! Но спасибо! –

+0

@AlexWaters: просто перейдите в Google, и вы найдете это: https://msdn.microsoft.com/en-us/library/ms190349.aspx – van

Смежные вопросы