2011-01-07 11 views
15

SQLalchemyの使用左外部結合を実行し、は、結合テーブルで一致する行をフィルタリングします。SQLalchemyの左結合でのフィルタリング

私はプッシュ通知を送信していますので、私はNotificationテーブルを持っています。これは、もはや有効ではないdevice_idsを格納するテーブルがExpiredDeviceIdであることを意味します。 (私は、ユーザーが後で通知を、その時点で再インストールアプリは、Appleのドキュメントによると再開すべきかもしれないとしてだけで影響を受けた通知を削除したくない)

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を取り戻す必要がありますか?あなたがライブデバイスIDを気にかけていない場合は、次のようにしてください:

+0

あなたはそうです。私は間違って、ExpiredDeviceIdが実際にオブジェクト参照であると仮定しました。一致する行がない場合、ExpiredDeviceId自体はNoneになります。しかし、実際にはクラス(テーブル)名であり、式は有効なSQLにコンパイルされます。 (私の質問の言葉遣いのために、私はそれが* IS * Noneであるかどうかを調べる必要があることに注意してください) –

+0

ああ、良い点、コードを編集して混乱を避けるために –

+1

'ExpiredDeviceId.expiration_time is None'これは.filter()に渡される前に常にFalseに評価され、予期しない動作を引き起こします(SQLを読み込むときにクエリを読み込むと予期しない動作が発生します)。 '=='を使用してください。 – Baczek