2011-10-30 44 views
119

我看了through the docs,我似乎無法找到如何在SQLAlchemy中執行OR查詢。我只想做這個查詢。在SQLAlchemy中使用OR

SELECT address FROM addressbook WHERE city='boston' AND (lastname='bulger' OR firstname='whitey') 

應該像

addr = session.query(AddressBook).filter(City == "boston").filter(????) 

回答

200

tutorial

from sqlalchemy import or_ 
filter(or_(User.name == 'ed', User.name == 'wendy')) 
+48

注意,這種方法支持使用發電機,所以如果你有事情或一個長長的清單,你可以做'過濾器(or_(User.name == v ('Alice','Bob','Carl')))' – robru

+20

@ Robru的建議是不必要的低效率。如果你已經有一個集合,那麼你應該像這樣使用'in_'運算符:'filter(User.name.in _(['Alice','Bob','Carl']))' – intgr

+2

啊,謝謝我沒有意識到sqlalchemy有那個過濾器 – robru

229

SQLAlchemy的重載位運算符&|~所以不是醜陋和難以閱讀前綴語法與or_()and_()(如在Bastien's answer),你可以使用這些運營商:

.filter((AddressBook.lastname == 'bulger') | (AddressBook.firstname == 'whitey')) 

注意,括號不是可有可無的由於位運算符的優先級。

所以你的整個查詢看起來是這樣的:

addr = session.query(AddressBook) \ 
    .filter(AddressBook.city == "boston") \ 
    .filter((AddressBook.lastname == 'bulger') | (AddressBook.firstname == 'whitey')) 
+8

+1,但是你可以改爲將最後兩個過濾器參數封裝在更多的括號中,並在它們和第一個(而不是第二個「過濾器」調用)之間使用「&」作爲相同的效果? –

+13

@ChaseSandmann:是的,你可以。但它會更可讀嗎? No. – ThiefMaster

17

or_運營商可以在數目不詳或查詢組件的情況下非常有用。

例如,我們假設我們正在創建一個REST服務,其中包含幾個可選的過濾器,如果任何過濾器返回true,應該返回記錄。另一方面,如果參數未在請求中定義,我們的查詢不應該改變。如果沒有or_功能,我們必須做這樣的事情:

query = Book.query 
if filter.title and filter.author: 
    query = query.filter((Book.title.ilike(filter.title))|(Book.author.ilike(filter.author))) 
else if filter.title: 
    query = query.filter(Book.title.ilike(filter.title)) 
else if filter.author: 
    query = query.filter(Book.author.ilike(filter.author)) 

隨着or_功能,它可以被改寫爲:

query = Book.query 
not_null_filters = [] 
if filter.title: 
    not_null_filters.append(Book.title.ilike(filter.title)) 
if filter.author: 
    not_null_filters.append(Book.author.ilike(filter.author)) 

if len(not_null_filters) > 0: 
    query = query.filter(or_(*not_null_filters)) 
3

這一直是真的很有幫助。 這是我對於任何給定表的實現:

def sql_replace(self, tableobject, dictargs): 

    #missing check of table object is valid 
    primarykeys = [key.name for key in inspect(tableobject).primary_key] 

    filterargs = [] 
    for primkeys in primarykeys: 
     if dictargs[primkeys] is not None: 
      filterargs.append(getattr(db.RT_eqmtvsdata, primkeys) == dictargs[primkeys]) 
     else: 
      return 

    query = select([db.RT_eqmtvsdata]).where(and_(*filterargs)) 

    if self.r_ExecuteAndErrorChk2(query)[primarykeys[0]] is not None: 
     # update 
     filter = and_(*filterargs) 
     query = tableobject.__table__.update().values(dictargs).where(filter) 
     return self.w_ExecuteAndErrorChk2(query) 

    else: 
     query = tableobject.__table__.insert().values(dictargs) 
     return self.w_ExecuteAndErrorChk2(query) 

# example usage 
inrow = {'eqmtvs_id': eqmtvsid, 'datetime': dtime, 'param_id': paramid} 

self.sql_replace(tableobject=db.RT_eqmtvsdata, dictargs=inrow) 
+0

對不起,我犯了一個小錯誤,chanhe以下行: query = select([tableobject])。where(and _(* filterargs)) – delpozov