1

我有以下 sqlalchemy 查询:

score = Scores.query.group_by(Scores.email).order_by(Scores.date).subquery()
students = db.session.query(Students, score.c.id).filter_by(archive=0).order_by(Students.exam_date).outerjoin(score, Students.email == score.c.email)

然后我用以下方式渲染这些东西:

return render_template('students.html', students=students.all())

现在,问题是我希望显示学生的最后一个分数,因为其中有很多对应于每个用户。但是第一个似乎被退回了。我在第一个查询得分上尝试了一些排序和 order_by,但没有成功。

如何影响并从“分数”中仅选择一个最新结果与“学生”中的相应行配对?

谢谢!

4

1 回答 1

2

首先,您要确保子查询仅选择特定学生的行。您可以使用以下correlate方法执行此操作:

score = db.session.query(Scores.id).order_by(Scores.date.desc()).correlate(Students)

仅此一项没有任何作用,因为您无法访问学生。的想法correlate是,如果您Students在子查询上使用,它不会将其添加到FROM列表中,而是依赖于提供它的外部查询。现在您将要优化您的查询(如果您愿意,可以使用连接条件):

score = score.filter(Students.email == Scores.email)

这将产生一个子查询,每次只返回一个学生的分数。剩下的问题是,如果每个学生都有多个分数。如果是这样,你需要限制它(如果没有,你也不需要order_by上面的部分):

score = score.limit(1)

现在您已确保查询返回单个标量值。由于您在选择上下文中使用查询,因此您需要将其转换为标量值:

students = db.session.query(Students, score.as_scalar()).filter_by(archive=0).order_by(Students.exam_date)

as_scalar方法是一种告诉 SQLAlchemy 这将返回单个 row 和 column的方法。因为否则您无法将其放入选择中。

注意limit如果你把as_scalar. 试用并过期。如果每个学生都只有一个分数,那么你根本不需要担心任何这些东西。

路上的一点提示:一个Query实例本身就是一个可迭代的。这意味着只要你不打印它或类似的东西,你就可以像列表一样传递一个查询,唯一的例外是真正只在访问时运行(惰性)并且你可以动态优化它,例如你可以切片it:students[:10]只会选择前 10 名学生(如果你在查询中执行它,它将作为 a 执行LIMIT而不是切片列表,前者效率更高)。

于 2013-09-28T03:24:20.713 回答