小编典典

sqlalchemy结合分组行的总和和计数

sql

嗨,我正在使用flask-sqlalchemy在Flask中进行一些小预测游戏,我有一个用户模型:

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    nick = db.Column(db.String(255), unique=True)
    bets = relationship('Bet', backref=backref("user"))

和我的投注模型

class Bet(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    uid = db.Column(db.Integer, db.ForeignKey('user.id'))
    matchid = db.Column(db.Integer, db.ForeignKey('match.id'))
    points = db.Column(db.Integer)

两者都不是完整的类,但应该针对问题进行处理。用户可以收集分数以预测比赛结果,并获得不同数量的分数以预测确切的结果,获胜者或与众不同。现在,我想列出最重要的用户,在这里我必须总结自己在做的要点

toplist = db.session.query(User.nick, func.sum(Bet.points)).\
    join(User.bets).group_by(Bet.uid).order_by(func.sum(Bet.points).desc()).all()

效果很好,现在可能有两个玩家得到相同的总积分。在这种情况下,正确的预测量(奖励3分)将确定获胜者。我可以通过以下方式获得此列表

tophits = db.session.query(User.nick, func.count(Bet.points)).\
            join(User.bets).filter_by(points=3).all()

它们都可以很好地工作,但是我认为必须有一种方法可以将两个查询放在一起,并获得一个包含用户名,点和“
hitcount”的表。我以前在SQL中已经做到了,但是我对SQLAlchemy和大脑中的思想难题并不那么熟悉。如何将两个查询合而为一?


阅读 223

收藏
2021-04-22

共1个答案

小编典典

在查询tophits只需更换COUNT/filter_by具有同等构造SUM(CASE(..))filter使WHERE两个条款是一样的。下面的代码应该做到这一点:

total_points = func.sum(Bet.points).label("total_points")
total_hits = func.sum(case(value=Bet.points, whens={3: 1}, else_=0)).label("total_hits")
q = (session.query(
        User.nick,
        total_points,
        total_hits,
        )
    .join(User.bets)
    .group_by(User.nick)
    .order_by(total_points.desc())
    .order_by(total_hits.desc())
    )

请注意,我更改了group_by子句以使用SELECT中的列,因为某些数据库引擎可能会抱怨。但是您不需要这样做。

2021-04-22