2016-06-13 78 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()