2016-06-13 73 views
1

我想实现一个选择与嵌套select子句,找到父母没有任何孩子。是我的表(从根本上简化)如下:sqlalchemy in_ subquery

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) 

在SQL我的查询将

select id from person where id not in (select person_id from foo); 

如何在Python和SQLAlchemy的实现呢?我发现这sqlalchemy, select using reverse-inclusive (not in) list of child column values,但它依赖于声明的关系。我不使用关系,因为我遇到了很多问题,其他线程大多数会过期或更改由其他线程缓存的数据,以及foo.person_id可以为null并且不引用任何内容。

我该怎么做?我尝试了in_和任何运算符的组合,引发了不同的异常。例如,这种尝试:

empty_persons = config.Session.query(Person).filter(Person.id.notin_(ChildTable.\ 
    person_id)).all() 

失败:in_()接受一个表达式列表或一个可选项。

这可能是一件简单的事情,但我只是不明白应该如何做。

ř

+1

难道你不能只在这儿加入ChildTable的Person吗? – reptilicus

+0

我不确定。问题是,在这种情况下,它是一个完全有效且可接受的情况,即在ChildTable中存在条目而不与Person链接(nullable = True)。我暂时用两个单独的查询解决了这个问题,但我觉得这不是正确的做法。 –

回答

6

使用子查询:

sub_stmt = config.Session.query(ChildTable.person_id) 
stmt = config.Session.query(Person).filter(~Person.id.in_(sub_stmt)) 
empty_persons = stmt.all() 

发出以下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) 

使用连接:

stmt = config.Session.query(Person).outerjoin(ChildTable).filter(ChildTable.person_id.is_(None)) 
empty_persons = stmt.all() 

发出以下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 

我认为两者都可以达到您想要的效果。

0

加入为我工作。谢谢。 在我的情况下,我试图找到属于特定客户的所有有序对象(主题)。我有3个表客户,订单,主题

stmt = db.session.query(Topics).outerjoin(Order).\ 
    filter(Order.cust_id == id) 

topics = stmt.all()