2011-01-07 17 views
15

Korzystanie z SQLalchemy Chcę wykonać lewe sprzężenie zewnętrzne i odfiltrować wiersze, które mają dopasowanie w połączonej tabeli.Filtrowanie po lewej stronie w SQLalchemy

Wysyłam powiadomienia push, więc mam tabelę Notification. Oznacza to, że mam również tabelę ExpiredDeviceId do przechowywania urządzeń device_ids, które nie są już poprawne. (Nie chcę po prostu usunąć porażone informację, jak użytkownik może później ponownie zainstalować aplikację, w którym momencie powiadomienia należy wznowić według docs Apple.)

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

Uwaga: nie może być wielokrotnością Powiadomienia na identyfikator urządzenia. Dla każdego urządzenia nie ma tabeli "Urządzenie".

Tak więc podczas wykonywania SELECT FROM Notification powinienem odpowiednio filtrować. Mogę to zrobić w SQL:

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

Ale jak mogę to zrobić w SQLalchemy?

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

Ewentualnie mogę zrobić z device_id NOT IN (SELECT device_id FROM ExpiredDeviceId) klauzuli, ale wydaje się, że sposób mniej efektywny.

Odpowiedz

13

Czy należy odrywać ExpiredDeviceId w krotce? Jeśli tego nie zrobisz (tzn. Dbasz tylko o urządzenia live device_ids), to nie możesz po prostu zrobić:

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

Masz rację. Niepoprawnie założyłem, że ExpiredDeviceId było w rzeczywistości odwołaniem do obiektu, a jeśli nie było pasującego wiersza, sam ExpiredDeviceId byłby Brak. Jednak w rzeczywistości jest to nazwa klasy (tabela), a wyrażenie jest kompilowane do poprawnego kodu SQL. (Zauważ, że dla sformułowania mojego pytania, muszę sprawdzić, czy to * JEST * Brak, które również działa). –

+0

Ach, dobry punkt, edytowałem fragment kodu, aby uniknąć pomyłki. –

+1

'ExpiredDeviceId.expiration_time is None' will not działa - zawsze będzie oceniał False przed przekazaniem do .filter(), powodując nieoczekiwane zachowanie (nieoczekiwane, jeśli spodziewasz się przeczytać zapytanie tak, jak czytasz SQL). Użyj '=='. – Baczek

Powiązane problemy