[英]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)
我从查询中想要的不是用户,而是通过“左外部联接”构造的(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.