sqlalchemy中的Order_by与外部联接

时间:2013-09-27 18:12:37

标签: python mysql join sqlalchemy outer-join

我有以下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,得分,但没有成功。

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

谢谢!

1 个答案:

答案 0 :(得分: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这会返回单行和列。因为否则你无法将它放入选择中。

注意:如果您放置limit,我并非100%确定您需要as_scalar。尝试一下,然后到期。如果每个学生只有一个分数,那么你根本不需要担心任何这些东西。

有点暗示:Query实例本身就是一个可迭代的。这意味着只要您不打印或类似,您就可以传递一个查询,就像一个列表一样,唯一的例外就是只能在访问(懒惰)上运行,并且您可以动态地优化它,例如您可以对其进行切片:students[:10]只会选择前10个学生(如果您在查询中执行此操作,则会将其作为LIMIT执行而不是切片列表,前者更有效)。