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

zed*_*gon 1 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()
Run Code Online (Sandbox Code Playgroud)

给我不同的错误,例如:

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Clients.orders has an attribute 'total'
Run Code Online (Sandbox Code Playgroud)

我想看看如何在 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')
Run Code Online (Sandbox Code Playgroud)

van*_*van 5

更新:更新了下面的查询以正确处理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)
    )
Run Code Online (Sandbox Code Playgroud)

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

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')
Run Code Online (Sandbox Code Playgroud)