我正在尝试为我想建立的国际象棋联赛创建数据库。
我在下面编写了查询,该查询可以为我提供所需的结果,但是看起来很冗长,我想就如何更好地编写它提出第二个意见。
我有两个表,一个代表一个团队,另一个代表“董事会”。董事会保留每个玩家的成绩及其所玩的董事会编号。
class Board(db.Model):
__tablename__ = 'board'
id = db.Column(db.Integer, primary_key=True)
board_number = db.Column(db.Integer)
team_id = db.Column(db.Integer, db.ForeignKey("team.id"))
result = db.Column(db.Float)
class Team(db.Model):
__tablename__ = 'team'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
boards = db.relationship('Board', backref='teams', lazy=True)
因此,要计算联赛表,我创建了4个不同的查询:胜利,失败,平局和总分。
然后将它们连接在一起并按总分排序以创建联赛表。
wins = (
db.session.query(Team.id,
db.func.count(Board.result).label('win')
)
.filter(Team.league_id == 1)
.join(Board).filter_by(team_id=Team.id, result=1)
.group_by(Team.id)
.subquery()
)
losses = (
db.session.query(Team.id,
db.func.count(Board.result).label('loss')
)
.filter(Team.league_id == 1)
.join(Board).filter_by(team_id=Team.id, result=0)
.group_by(Team.id)
.subquery()
)
draws = (
db.session.query(Team.id,
db.func.count(Board.result).label('draw')
)
.filter(Team.league_id == 1)
.join(Board).filter_by(team_id=Team.id, result=0.5)
.group_by(Team.id)
.subquery()
)
total_points = (
db.session.query(Team.id,
db.func.sum(Board.result).label('total')
)
.filter(Team.league_id == 1)
.join(Board, (Board.team_id == Team.id))
.group_by(Team.id)
.subquery()
)
league_table = (
db.session.query(Team.name, wins.c.win, draws.c.draw, losses.c.loss, total_points.c.total)
.join((wins, wins.c.id == Team.id))
.join((losses, losses.c.id == Team.id))
.join((draws, draws.c.id == Team.id))
.join((total_points, total_points.c.id == Team.id))
.order_by((total_points.c.total).desc())
.all()
)
这4个查询可以合并为一个吗?
答案 0 :(得分:1)
可以使用聚合FILTER
子句在单个查询中执行查询:
如果指定了
FILTER
,则只有filter_clause
评估为true的输入行才被馈送到聚合函数;
在SQLAlchemy中,您可以使用FunctionElement.filter()
来产生子句:
db.session.query(
Team.name,
db.func.count(Board.result).filter(Board.result == 1).label('win'),
db.func.count(Board.result).filter(Board.result == 0).label('loss'),
db.func.count(Board.result).filter(Board.result == 0.5).label('draw'),
db.func.sum(Board.result).label('total'))\
.join(Board)\
.filter(Team.league_id == 1)\
.group_by(Team.id)\
.order_by(db.func.sum(Board.result).desc())