SQLAlchemy - 包含在多对多关系上调用 func.count() 导致 0 的行

问题描述 投票:0回答:1

我正在查询表

Team
以获取所有团队的列表。该查询对象被输入到利用 sqlalchemy 的
paginate()
的分页函数。

该函数接受

order
order_by
的输入,确定结果查询的列和顺序。当直接对
Team
的一个属性执行排序时,这种方法效果很好,但我也想根据每个记录与另一个表
Player
的关系数执行排序。

使用

func.count()
.join()
.group_by()
这是可能的 - 但是,如果球队没有任何球员记录,则查询中会忽略该记录。我想包含此查询中的所有结果。

我曾想过创建第二个查询,忽略第一个查询的结果,然后以某种方式将它们组合起来,然后将它们传递给分页函数,但我还没有找到一种方法来做到这一点。

有没有办法包含

count
应返回
0
的结果,或者是否有其他方法可以实现此效果?

功能:

def get_teams(filters):
    """Get the collection of all teams"""
    page = filters['page']
    per_page = filters['per_page']
    order = filters['order']  # validates as either 'asc' or 'desc'
    order_by = filters['order_by']

    if order_by == 'active_players':  # checks if sort needs to be done manually
        query = db.session.query(Team, sa.func.count(PlayerTeam.id).label('count')) \
            .join(Team.player_association) \
            .filter(PlayerTeam.end_date == None) \
            .group_by(Team) \
            .order_by(getattr(sa, order)('count'))
    else:  # sort is directly on attribute, this is easy
        query = sa.select(Team).order_by(getattr(sa, order)(getattr(Team, order_by)))

    return Team.to_collection_dict(query, page, per_page)

型号:

class Team(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), index=True, unique=True, nullable=False)
    # some other fields

    player_association = db.relationship('PlayerTeam', back_populates='team',lazy='dynamic')
    players = association_proxy('player_association', 'player')

    @staticmethod
    def to_collection_dict(query, page, per_page):
        resources = db.paginate(query, page=page, per_page=per_page, error_out=False)
        # convert resources to dict and return

class Player(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    player_name = db.Column(db.String(64), nullable=False)
    # some other fields

    team_association = db.relationship('PlayerTeam', back_populates='player', lazy='dynamic')
    teams = association_proxy('team_association', 'team')

class PlayerTeam(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    player_id = db.Column(db.Integer, db.ForeignKey('player.id'))
    team_id = db.Column(db.Integer, db.ForeignKey('team.id'))
    end_date = db.Column(db.DateTime)
    # some other fields

    player = db.relationship('Player', back_populates='team_association')
    team = db.relationship('Team', back_populates='player_association')
python sqlalchemy flask-sqlalchemy
1个回答
0
投票

感谢使用 @snakecharmerb 的

.outerjoin
的建议,我找到了一个可行的解决方案。

单独使用外连接仍然会导致计数为 0 的行不被返回,但通过将附加过滤器移动到外连接的条件包括所有行。

修改查询

query = db.session.query(Team, sa.func.count(PlayerTeam.id).label('count')) \
    .outerjoin(PlayerTeam,
               (Team.id == PlayerTeam.team_id) & (PlayerTeam.end_date.is_(None))
              ) \
    .group_by(Team) \
    .order_by(getattr(sa, order)('count'))```
© www.soinside.com 2019 - 2024. All rights reserved.