我有以下型號在我的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