2014-09-23 65 views
0

至少一個B我有兩個表:SQLAlchemy的,選擇這樣一個具有與凸起標誌

class A(Base): 
    id = Column(Integer, primary_key=True) 

class B(Base): 
    id = Column(Integer, primary_key=True) 

    a_id = Column(Integer, ForeignKey('a.id')) 
    a = relationship(A) 
    flag = Column(Boolean, default=False) 

正如你所看到的 - 從B中的每個對象從一個關係到一個對象,也更多的B中的一個對象可能與A中的單個對象有關。
我需要選擇所有A中至少有一個與標誌== False相關的B。
現在我想的東西是這樣的:

selection = session.query(A).\ 
     join(B).\ 
     filter(
      B.a_id == A.id, 
      B.flag == False, 
     ).\ 
     group_by(A) 

但我不知道兩件事情:

  1. 如果該查詢是正確的? (我正在處理大量的數據,測試它非常複雜)。

  2. 如果此查詢從sqlalchemy哲學的角度來看是正確的? (我是新手)。

回答

1

添加backref的關係:

class B(Base): 
    # ... 
    a = relationship(A, backref="b_s") 

然後sqlalchemy verino的@歐文的SQL版本低於:

qry = session.query(A).filter(A.b_s.any(B.flag == False)) 

如果你不想或者不能添加backref的關係,下面將爲簡單情況產生相同的查詢,但如果您有更復雜的查詢,您應該留意生成的SQL,因爲連接可能需要更多調整:

qry = (session.query(A).filter(
    exists(select([1]).where(B.a_id == A.id).where(B.flag == False))) 
) 
+0

是否有可能沒有後端? – sennoy 2014-09-23 14:09:43

+0

用選項更新了一個答案,沒有backref – van 2014-09-23 15:59:45

+0

謝謝!而已 – sennoy 2014-09-24 16:32:10

1

一個配件的查詢是與EXISTS半連接:

SELECT * FROM A 
WHERE EXISTS (SELECT 1 FROM B WHERE a_id = A.id AND flag = FALSE); 

對於這個要快,你應該有B任何指數與a_id作爲唯一或第一個表達式。如果這與條件flag = FALSE是常見的查詢,可以考慮像部分索引

CREATE INDEX b_some_nmae_idx ON b(a_id) WHERE flag = FALSE; 

加入到所有匹配的行中B並再次聚集(如你有問題)是很多無意義工作。 EXISTS只要找到B中的第一個匹配行即可停止。

+0

感謝您的回答。實際上,我知道如何在原始SQL中執行它:)我需要使用sqlalchemy執行相同的操作。 – sennoy 2014-09-23 03:10:21

+0

@sennoy:正如我添加到我的答案:您現在的查詢不是* SQL *中的最佳選擇。 – 2014-09-23 03:13:26

相關問題