繁体   English   中英

SQLAlchemy与子查询和多个映射器联接

[英]SQLAlchemy join with subquery and multiple mappers

根据SQLAlchemy文档,可以执行以下操作:

address_subq = session.query(Address).\
            filter(Address.email_address == 'ed@foo.com').\
            subquery()

q = session.query(User).join(address_subq, User.addresses)

SQLA文档,“高级定位”部分

我从查询中想要的不是用户,而是通过“左外部联接”构造的(User,Address)元组,因此如果用户没有地址,我将得到(User,Address)或(User,None)元组或(子查询?)过滤器从用户地址列表中删除了该地址(如果他们不符合过滤器的条件)。

address_subq = session.query(Address).\
            filter(Address.email_address == 'ed@foo.com').\
            subquery()

q = session.query(User, Address).outerjoin(address_subq, User.addresses)

我将示例改编为实际班级,但没有用。 我曾尝试使用“相关”和“混淆”,但确实找到了解决方案。 我需要更改使其工作吗?

这将是我追求的SQL:

SELECT
   user.name, addr.email
FROM
   user
      LEFT OUTER JOIN
   (SELECT
      address.name, address.user_id
   FROM
      address
   WHERE
      address.email LIKE '%foo.com%') AS addr ON user.id = addr.user_id

如果您已经包含了要执行的目标SQL语句,将会更加清楚,但是我假设您要查询用户中的所有字段以及email_address与某个特定值匹配的地址。 如果这是您想要的,那么简单的连接就足够了,可以完全避免子查询。 对于sqlalchemy,可以使用select_from从表中进行显式选择,并且具有一个示例,该示例可能适合于您的特定用例,例如:

>>> q = session.query(User, Address).select_from(User).join(Address).filter(
...     Address.email_address == 'ed@foo.com')
>>> print(q)
SELECT users.id AS users_id, users.name AS users_name, ... 
    addresses.email_address ..., addresses.user_id ...,
FROM users JOIN addresses ON users.id = addresses.user_id 
WHERE addresses.email_address = ?

哪个应该与用户一起返回结果以及给定email_address的地址。

当然(根据此处的注释),由于在这种情况下User是在主查询中,因此可以针对此特定实例省略select_from ,但这对于sqlalchemy如何构造查询仍然很有用。


如果你想具体列(原来,你是不是你的(用户地址)的元组的意思明确,那意味着整个类,这是被已经返回什么),简单地传递你想要的属性如记录在查询部分

对于您的预期部分,您需要使用子查询作为查询参数,而不是Address ,并使用手动联接,如本教程的“ 使用子查询”部分中再次指定的那样。

您问题中的address_subq可以按原样使用,但是如果您要替换内部查询,使其更像您以后指定的内容,请尝试:

address_subq = session.query(Address).filter(
    Address.email_address.like('%@foo.com')).subquery()

满足您要求的最终查询将是:

q = session.query(
     User.name, address_subq.c.email_address
).outerjoin(
     address_subq, User.id==address_subq.c.user_id)

打印并执行查询(已修改打印输出以提高可读性)

>>> print(q)
SELECT users.name AS users_name, anon_1.email_address AS anon_1_email_address 
FROM users LEFT OUTER JOIN (
    SELECT addresses.id AS id,
           addresses.email_address AS email_address,
           addresses.user_id AS user_id 
    FROM addresses 
    WHERE addresses.email_address LIKE ?
) AS anon_1 ON users.id = anon_1.user_id
>>> q.all()
[('ed', 'ed@foo.com'), ('wendy', None), ('mary', None), ('fred', None), ('jack', None)]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM