【发布时间】:2017-05-07 07:40:53
【问题描述】:
可以使用单个 SQLAlchemy session.query 完成以下 MySQL 查询还是必须运行第二个 session.query ?如果有,怎么会?
Select *, (select c from table2 where id = table1.id) as d from table1 where foo = x
【问题讨论】:
标签: python sqlalchemy
可以使用单个 SQLAlchemy session.query 完成以下 MySQL 查询还是必须运行第二个 session.query ?如果有,怎么会?
Select *, (select c from table2 where id = table1.id) as d from table1 where foo = x
【问题讨论】:
标签: python sqlalchemy
你想要的是 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()
将有权访问来自 Table2 的子(或父)记录,即使我们在这里没有要求它 - 因为直接在模型中定义的关系正在为我们处理。查看 SQLAlchemy 文档中的"Relationship Loading Techniques",了解有关其工作原理的更多信息。
【讨论】:
Query.label() 和 Query.as_scalar() 显式处理。