Sqlalchemy in_子查询

Ric*_*ark 7 python sqlalchemy

我正在尝试使用嵌套的select子句实现一个select,以找到没有任何子节点的父节点.我的表格(从根本上简化)如下:

class Person(Base):
    __tablename__ = "person"
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=True, default=None)

class ChildTable(Base):
    __tablename__ = "foo"
    id = Column(Integer, primary_key=True)
    data = Column(String)
    person_id = Column(Integer, ForeignKey("person.id"), nullable=True)
Run Code Online (Sandbox Code Playgroud)

在sql我的查询将是

select id from person where id not in (select person_id from foo);
Run Code Online (Sandbox Code Playgroud)

我如何在Python和sqlalchemy中实现它?我发现这个sqlalchemy,选择使用反向包含(不在)的子列值列表,但它依赖于声明的关系.我没有使用关系,因为我遇到了很多问题,主要是其他线程过期或更改其他线程缓存的数据,以及foo.person_id可以为null而不引用任何内容.

我该怎么做呢?我尝试了in_和任何运算符的组合,抛出了不同的异常.例如这个尝试:

empty_persons = config.Session.query(Person).filter(Person.id.notin_(ChildTable.\
    person_id)).all()
Run Code Online (Sandbox Code Playgroud)

这失败:in_()接受表达式列表或可选择的表达式.

这可能是一件简单的事情,但我不明白应该怎么做.

[R

Hal*_*Ali 17

使用子查询:

sub_stmt = config.Session.query(ChildTable.person_id)
stmt = config.Session.query(Person).filter(~Person.id.in_(sub_stmt))
empty_persons = stmt.all()
Run Code Online (Sandbox Code Playgroud)

发出以下sql:

SELECT person.id AS person_id, person.name AS person_name
FROM person
WHERE person.id NOT IN (SELECT foo.person_id AS foo_person_id
FROM foo)
Run Code Online (Sandbox Code Playgroud)

使用连接:

stmt = config.Session.query(Person).outerjoin(ChildTable).filter(ChildTable.person_id.is_(None))
empty_persons = stmt.all()
Run Code Online (Sandbox Code Playgroud)

发出以下sql:

SELECT person.id AS person_id, person.name AS person_name
FROM person LEFT OUTER JOIN foo ON person.id = foo.person_id
WHERE foo.person_id IS NULL
Run Code Online (Sandbox Code Playgroud)

我认为两者都能达到你想要的结果.