2017-05-07 120 views

回答

1

你想要的是SQLAlchemy的的subquery对象。本质上,您按照正常方式编写查询,但不是通过.all().first()(如通常直接返回某种结果所做的那样)结束查询,而是通过.subquery()结束查询以返回子查询对象。子查询对象基本上生成嵌入别名中的子查询SQL,但不运行它。然后,您可以在主查询中使用它,SQLAlchemy将发出必要的SQL以在单个操作中执行查询和子查询。

比方说,我们有以下student_scores表:

+------------+-------+-----+ 
| name | score | age | 
+------------+-------+-----+ 
| Xu Feng | 95 | 25 | 
| John Smith | 88 | 26 | 
| Sarah Taft | 89 | 25 | 
| Ahmed Zaki | 86 | 26 | 
+------------+-------+-----| 

(忽略可怕的数据库设计)

在这个例子中,我们希望得到一个包含所有的学生和他们的分数结果集,按年龄加入平均分数。在原始的SQL语句,我们会做这样的事情:

SELECT ss.name, ss.age, ss.score, sub.average 
    FROM student_scores AS "ss" 
    JOIN (SELECT age, AVG(score) AS "average" 
      FROM student_scores 
     GROUP BY age) AS "sub" 
     ON ss.age = sub.age 
ORDER BY ss.score DESC 

结果应该是这样的:

+------------+-------+-----+---------+ 
| name | score | age | average | 
+------------+-------+-----+---------+ 
| Xu Feng | 95 | 25 | 92 | 
| John Smith | 88 | 26 | 87 | 
| Sarah Taft | 89 | 25 | 92 | 
| Ahmed Zaki | 86 | 26 | 87 | 
+------------+-------+-----|---------+ 

在SQLAlchemy中,我们可以先定义自身的子查询:

from sqlalchemy.sql import func 

avg_scores = (
    session.query(
     func.avg(StudentScores.score).label('average'), 
     StudentScores.age 
    ) 
    .group_by(StudentScores.age) 
    .subquery() 
) 

现在我们的子查询被定义了,但是没有语句实际上被发送到数据库。不过,我们可以把我们的子查询的对象几乎好像它是另一个表中,写我们的主查询:

results = (
    session.query(StudentScores, avg_scores) 
    .join(avg_scores, StudentScores.age == avg_scores.c.age) 
    .order_by('score DESC').all() 
) 

只不过现在是向数据库发出的任何SQL,并且我们得到了相同的结果生子查询例子。

话虽如此,你提供的例子实际上很平凡,根本不需要子查询。根据你的关系是如何定义的,SQLAlchemy的可热切负载相关的对象,从而使对象通过返回:

results = session.query(Table1).filter(Table1.foo == 'x').all() 

将有从表2对该子女的探视(或父母)结果,即使我们没这里没有要求 - 因为直接在模型中定义的关系是为我们处理的。请查看SQLAlchemy文档中的"Relationship Loading Techniques"以获取更多关于它如何工作的信息。

+0

什么OP后看起来像一个标量子查询,它[[Query.label()'](http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query。 Query.label)和['Query.as_scalar()'](http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.as_scalar)明确处理。 –

相关问题