2016-09-30 62 views
1

計數鑑於這些SQLAlchemy的模型定義:子查詢與SQLAlchemy的

class Store(db.Model): 
    __tablename__ = 'store' 

    id = Column(Integer, primary_key=True) 
    name = Column(String, nullable=False) 


class CustomerAccount(db.Model, AccountMixin): 
    __tablename__ = 'customer_account' 

    id = Column(Integer, primary_key=True) 
    plan_id = Column(Integer, ForeignKey('plan.id'), index=True, nullable=False) 

    store = relationship('Store', backref='account', uselist=False) 
    plan = relationship('Plan', backref='accounts', uselist=False) 


class Plan(db.Model): 
    __tablename__ = 'plan' 

    id = Column(Integer, primary_key=True) 
    store_id = Column(Integer, ForeignKey('store.id'), index=True) 
    name = Column(String, nullable=False) 
    subscription_amount = Column(Numeric, nullable=False) 
    num_of_payments = Column(Integer, nullable=False) 
    store = relationship('Store', backref='plans') 

如何編寫一個查詢的計劃,讓訂閱收入的明細? 我想找回給定商店的計劃清單,併爲每個計劃計算該計劃的總收入,計算方法是將Plan.subscription_amount * Plan.num_of_payments *訂閱該計劃的客戶數量相乘計算得出

目前,我試圖與此查詢和子查詢:

store = db.session.query(Store).get(1) 

subscriber_counts = db.session.query(func.count(CustomerAccount.id)).as_scalar() 

q = db.session.query(CustomerAccount.plan_id, func.sum(subscriber_counts * Plan.subscription_amount * Plan.num_of_payments))\ 
    .outerjoin(Plan)\ 
    .group_by(CustomerAccount.plan_id) 

問題是子查詢不能在當前計劃的ID過濾。

我也試圖與該另一種方法(無子查詢):

q = db.session.query(CustomerAccount.plan_id, func.count(CustomerAccount.plan_id) * Plan.subscription_amount * Plan.num_of_payments)\ 
    .outerjoin(Plan)\ 
    .group_by(CustomerAccount.plan_id, Plan.subscription_amount, Plan.num_of_payments) 

雖然結果似乎很好,我不知道如何回到計劃名稱或其他計劃列,如我d需要通過(並改變結果)將它們添加到組中。

理想情況下,如果一個計劃沒有任何訂閱者,我希望它返回總數爲零。

謝謝!

回答

1

感謝Alex格隆霍姆在#sqlalchemy我結束了這個工作的解決方案:

from sqlalchemy.sql.expression import label 
from sqlalchemy.sql.functions import coalesce 

from instalment.models import db 
from sqlalchemy import func, desc 


def projected_total_money_volume_breakdown(store): 
    subscriber_counts = db.session.query(CustomerAccount.plan_id, func.count(CustomerAccount.id).label('count'))\ 
     .group_by(CustomerAccount.plan_id)\ 
     .subquery() 

    total_amount_exp = coalesce(subscriber_counts.c.count, 0) * Plan.subscription_amount * Plan.num_of_payments 

    return db.session.query(Plan, label('total_amount', total_amount_exp))\ 
     .outerjoin(subscriber_counts, subscriber_counts.c.plan_id == Plan.id)\ 
     .filter(Plan.store == store)\ 
     .order_by(desc('total_amount'))\ 
     .all()