如何连接3个表并执行func.sum

时间:2014-06-26 03:41:00

标签: python sql sqlite sqlalchemy

如何加入3个表,客户端,订单和存款,并对数据库中存在的每个Client.id在Orders.total和Deposits.total上执行func.sum?查询结果应包括Clients.email,func.sum(Orders.total)和func.sum(Deposits.total)列。

到目前为止,我已经尝试了不同的查询:

listeclients = db.session.query(Clients,func.sum(Clients.orders.total).\
    label("ctotal"),func.sum((Clients.deposits.total).\
    label("dtotal"))).group_by(Client.id).all()

给我不同的错误,例如:

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Clients.orders has an attribute 'total'

我想看看如何在sqlalchemy中做到这一点,但我也会接受这种查询逻辑背后的暗示......

我的映射是否正确?这种连接的语法是什么?我应该在某个地方使用eagerload吗?我已经成功完成了更简单的查询,但是现在这样的人就是我的头脑!欢迎任何帮助,即使只是原始SQL中的逻辑。我被卡住了......

class Clients(db.Model):
    __tablename__ = 'clients'    
    id = db.Column(db.Integer, primary_key = True)
    email = db.Column(db.String(60), index = True, unique = True)
    adresse = db.Column(db.String(64), index = True)
    telephone = db.Column(db.String(10), index = True)
    confirmed = db.Column(db.Boolean, default = False)
    orders = db.relationship('Orders')
    deposits = db.relationship('Deposits') 

class Orders(db.Model):
    __tablename__ = 'orders'    
    id = db.Column(db.Integer, primary_key = True)
    client_id = db.Column(db.Integer, db.ForeignKey('clients.id'))
    total = db.Column(db.Float)
    date = db.Column(db.DateTime, index = True, default=datetime.now)    
    client = db.relationship('Clients')

class Deposits(db.Model):
    __tablename__='deposits'
    id = db.Column(db.Integer, primary_key = True)
    date = db.Column(db.DateTime, index = True, default=datetime.now)    
    client_id = db.Column(db.Integer, db.ForeignKey('clients.id'))
    total = db.Column(db.Float)  
    cheque = db.Column(db.Boolean)
    client = db.relationship('Clients')

2 个答案:

答案 0 :(得分:1)

更新更新了以下查询,以便正确处理sum

sq1 = (db.session.query(Orders.client_id, func.sum(Orders.total).label("ctotal"))
        .group_by(Orders.client_id)).subquery("sub1")

sq2 = (db.session.query(Deposits.client_id, func.sum(Deposits.total).label("dtotal"))
        .group_by(Deposits.client_id)).subquery("sub2")

q = (db.session.query(Clients, sq1.c.ctotal, sq2.c.dtotal)
    .outerjoin(sq1, sq1.c.client_id == Clients.id)
    .outerjoin(sq2, sq2.c.client_id == Clients.id)
    )

此外,您可以简单地使用backref

,而不是两次定义关系(在某些版本的sqlalchemy上实际上可能会失败)。
class Clients(db.Model):
    orders = db.relationship('Orders', backref='client')
    deposits = db.relationship('Deposits', backref='client') 

class Orders(db.Model):
    # client = db.relationship('Clients')

class Deposits(db.Model):
    # client = db.relationship('Clients')

答案 1 :(得分:0)

在sql中它很简单:

select c.email, sum(o.total), sum(d.total)
from Clients c
left join Orders o
    on ...
left join Deposits d
    on ...
group by c.email