2011-01-07 105 views
15

使用SQLalchemy我想要執行左外部連接,並且過濾出在連接表中匹配的行。在左連接中過濾SQLalchemy

我發送推送通知,所以我有一個Notification表。這意味着我還有一個ExpiredDeviceId表來存儲不再有效的device_id。 (我不希望只是刪除受影響的通知,爲用戶可能會在以後重新安裝應用程序,此時通知應根據蘋果的文檔恢復。)

CREATE TABLE Notification (device_id TEXT, time DATETIME); 
CREATE TABLE ExpiredDeviceId (device_id TEXT PRIMARY KEY, expiration_time DATETIME); 

注:可能有多個每個device_id的通知。每個設備沒有「設備」表。

所以當做SELECT FROM Notification我應該相應地過濾。我可以在SQL中執行:

SELECT * FROM Notification 
    LEFT OUTER JOIN ExpiredDeviceId 
    ON Notification.device_id = ExpiredDeviceId.device_id 
WHERE expiration_time IS NULL 

但是我怎麼能在SQLalchemy中做到這一點?

sess.query(
    Notification, 
    ExpiredDeviceId 
).outerjoin(
    (ExpiredDeviceId, Notification.device_id == ExpiredDeviceId.device_id) 
).filter(
    ??? 
) 

或者我可以用一個device_id NOT IN (SELECT device_id FROM ExpiredDeviceId)條款做到這一點,但似乎這樣效率較低。

回答

13

你是否需要拉回元組中的ExpiredDeviceId?如果你不這樣做(即你只關心live device_ids),那你難道不能這樣做:

sess.query(
    Notification 
).outerjoin(
    (ExpiredDeviceId, Notification.device_id == ExpiredDeviceId.device_id) 
).filter(
    ExpiredDeviceId.expiration_time == None 
) 
+0

你說得對。我錯誤地認爲ExpiredDeviceId實際上是一個對象引用,如果沒有匹配的行,ExpiredDeviceId本身就是None。然而,它實際上是一個類(表)名稱,並且該表達式被編譯爲有效的SQL。 (請注意,對於我的問題的措辭,我需要檢查它* IS *無,這也是有效的。) – 2011-01-10 16:53:19