SQLAlchemy如何合并查询

时间:2019-03-04 16:20:51

标签: python postgresql sqlalchemy

我正在尝试为我想建立的国际象棋联赛创建数据库。

我在下面编写了查询,该查询可以为我提供所需的结果,但是看起来很冗长,我想就如何更好地编写它提出第二个意见。

我有两个表,一个代表一个团队,另一个代表“董事会”。董事会保留每个玩家的成绩及其所玩的董事会编号。

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个查询可以合并为一个吗?

1 个答案:

答案 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())