我有以下型号在我的DB(瓶-SQLAlchemy中,声明的方式,简化):如何用SQLAlchemy求和* count *子查询?
class Player(db.Model):
id = db.Column(db.Integer, primary_key = True)
...
class Game(db.Model):
id = db.Column(db.Integer, primary_key = True)
creator_id = db.Column(db.Integer, db.ForeignKey('player.id'))
creator = db.relationship(Player, foreign_keys='Game.creator_id')
opponent_id = db.Column(db.Integer, db.ForeignKey('player.id'))
opponent = db.relationship(Player, foreign_keys='Game.opponent_id')
winner = db.Column(db.Enum('creator', 'opponent'))
每场比赛可以是韩元,丢失或平局收场。 我需要通过“赢率”为了让玩家对它们进行排序 - 即:
- 如果玩家创建了一个游戏,那场比赛的获胜者
creator
,它被认为是双赢; - 如果玩家被邀请参加比赛作为对手并且游戏的获胜者是
opponent
,那么它也被视为赢; - 此玩家参与的其他游戏被视为丢失游戏。
所以我的算法如下:
@hybrid_property
def winrate(self):
games = Game.query.filter(or_(
Game.creator_id == self.id,
Game.opponent_id == self.id,
))
count = 0
wins = 0
for game in games:
count += 1
if game.creator_id == self.id and game.winner == 'creator':
wins += 1
elif game.opponent_id == self.id and game.winner == 'opponent':
wins += 1
if count == 0:
return 0
return wins/count
,这个方法工作时,我想确定赢率特定的球员;但是当我想按胜率排序时,它就失败了。 我试图重写它的SQL和得到的东西是这样的:
SELECT * FROM player
ORDER BY ((SELECT count(g1.id) FROM game g1
WHERE g1.creator_id = player.id AND g1.winner = 'creator'
) + (SELECT count(g2.id) FROM game g2
WHERE g2.opponent_id = player.id AND g2.winner = 'opponent'
))/(SELECT count(g3.id) FROM game g3
WHERE player.id IN (g3.creator_id, g3.opponent_id)
)
这不处理球员没有比赛,但一般应工作。没有游戏的玩家可以用MySQL CASE
声明处理。
但问题是我无法确定如何使用SQLAlchemy编码此SQL。 这里是(简化)代码,我尝试使用:
@winrate.expression
def winrate(cls):
cnt = Game.query.filter(
cls.id.in_(Game.creator_id, Game.opponent_id)
).with_entities(func.count(Game.id))
won = Game.query.filter(
or_(
and_(
Game.creator_id == cls.id,
Game.winner == 'creator',
),
and_(
Game.opponent_id == cls.id,
Game.winner == 'opponent',
),
)
)
return case([
(count == 0, 0),
], else_ = (
won/count
))
当谈到won/count
线告诉我,Query
不能Query
分割该代码失败。我尝试使用子查询,但没有任何成功。
我应该如何实现它?或者,也许我应该使用某种连接/任何? (DB计划不能更改。)
没有实际看到或思考太辛苦一下:'won.scalar()/ count.scalar() '? 'Query.scalar()'产生一个标量子查询,它是子句元素 – Eevee
Query.scalar()返回数字,而不是子查询。 – MarSoft
啊,对不起,我的意思是'Query.as_scalar()':) – Eevee