如何在sqlalchemy中创建子查询

47
SELECT *
FROM Residents
WHERE apartment_id IN (SELECT ID
                       FROM Apartments
                       WHERE postcode = 2000)

我正在使用SQLAlchemy并尝试执行上述查询。 我无法使用db.engine.execute(sql)以原始SQL执行它,因为它会抱怨我的关系不存在...但是我可以使用以下格式成功查询我的数据库:session.Query(Residents).filter_by(???)。 我不知道如何使用这种格式构建我想要的查询。

2个回答

102

您可以使用subquery方法创建子查询。

subquery = session.query(Apartments.id).filter(Apartments.postcode==2000).subquery()
query = session.query(Residents).filter(Residents.apartment_id.in_(subquery))

8
谢谢您,我的大人。终于有一个不涉及与ORM混乱打交道的答案了。 - Eric Martin
查询的类型是<class 'flask_sqlalchemy.BaseQuery'>。你如何从中获取数据?我可以看到它有.all()方法,但一旦我调用它,Flask就会返回错误,例如:sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: appointments.done - thanos.a
1
我不清楚如何使用这种方法将子查询“参数”绑定到主查询(因为子查询在查询本身之前定义)。 - castarco
1
在SQLAlchemy 1.4中,这种用法会给我一个警告:SAWarning: Coercing Subquery object into a select() for use in IN(); please pass a select() construct explicitly。是否有此问题的示例格式?我还没有在文档中找到。 - Zoupah
2
回答了自己的简单问题。只需按照以下方式编写即可解决警告: from sqlalchemy.sql import selectquery = session.query(Residents).filter(Residents.apartment_id.in_(select(subquery))) - Zoupah
显示剩余2条评论

4

我想补充一句,如果您使用这种方法来更新您的数据库,请确保添加synchronize_session='fetch'参数。代码应该类似于:

subquery = session.query(Apartments.id).filter(Apartments.postcode==2000).subquery()
query = session.query(Residents).\
          filter(Residents.apartment_id.in_(subquery)).\
          update({"key": value}, synchronize_session='fetch')

否则你会遇到问题。

11
请问需要翻译的内容是:"what kind of issues, care to expand?" 翻译为中文是:"有哪些问题,能详细说明一下吗?" - hjpotter92
2
@hjpotter92,您可以在文档中阅读此内容。但是一般来说,如果您已经在内存中有一些Resident对象,则此更新也会更新这些内存中的对象。否则,这些对象将过时,可能会导致错误。但是,synchronize_session也很慢,这也不好。 - Andrio Skur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接