【问题标题】:SQLAlchemy: Sum all Child column attributes while querying Parent?SQLAlchemy:在查询父时对所有子列属性求和?
【发布时间】:2016-12-14 22:00:08
【问题描述】:

TeamLeague 之间存在多对一关系

以下代码加入表格,并按goals_forleague 中的每个team 排序联赛:

for league in League.query.join(League.teams).order_by(desc(Team.goals_for)):
    total_goals = 0
    for team in league.teams:
        total_goals += team.goals_for

    print("Total goals scored in", league.full_name, "is", total_goals)

正确产生:

德甲总进球数为 22

英超联赛总进球数为 15

我想知道两件事:

  1. 鉴于teams 基本上是一个列表,因此没有属于每个team 实例的total_goals,有没有办法在没有for 循环的情况下对team 目标的值求和?

  2. 如果 1 是可能的,它是否比上面的 for 循环更快/更好?

【问题讨论】:

  • 你试过sum(league.teams)吗?应该更快*,因为sum 是在 C 中实现的。*YMMV
  • 但我需要每个teamgoals_for 列,而不是团队的数量。
  • 抱歉,误读了正在发生的事情。 sum(team.goals_for for team in league.teams) 大致相当于,但作为生成器表达式并使用sum
  • 这不是所谓的理解,只是更快的for循环吗? (说话很菜鸟?)
  • 理解与生成器表达式不同。有关更多详细信息,请参阅this question。它们通常更快,因为它们不会将所有项目都保存在内存中。因此,如果您只使用这些值一次,则生成器表达式可能是最佳的。阅读PEP0289 可能会很好。

标签: python sql sqlalchemy flask-sqlalchemy


【解决方案1】:

为什么不尝试直接从SQL 查询中获取聚合结果,并避免从数据库中检索额外数据并加载整个关系树。

以下应该会给你一个想法:

from sqlalchemy import func

q = (
    session
    .query(League.full_name, func.sum(Team.goals_for).label("total_goals"))
    .join(Team, League.teams)
    .group_by(League.full_name)
)

for full_name, total_goals in q:
    print("Total goals scored in", full_name, "is", total_goals)

【讨论】:

  • 我赞成并选择了这个,因为我经常在 SQLAlchemy 线程中看到你的名字,但我不得不承认我不太明白我们如何在这里避免整个关系树。我知道没有加入,但是如何获得团队?这种查询的“良好经济学”从何而来?
  • 良好的经济效益来自于这样一个事实,即这只是对数据库的一次SQL 查询。
  • 实际上,这里需要加入,所以这显然是我的遗漏。我会修改的。
  • 谢谢。我仍然不明白 where 是我原始帖子中的附加查询。 (另外:无法通过您的个人资料与您取得联系,我很想雇用您进行项目)
  • 根据关系League.teams 的配置方式(例如是否使用joinedload),您的第一个查询将加载Team 对象。只有当您通过 league.teams(代码的第 3 行)访问它时,才会发出另一个 SQL 查询。您可以通过记录 SQL 语句 (engine.echo = True) 来检查。但即使你的关系是自动加载的,我认为在数据库中计算每个联赛的总数比在 python 代码中要快得多。加上数据库和代码之间的数据传输更小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 2022-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
相关资源
最近更新 更多