在SQLalchemy中对左连接进行过滤

22 投票
1 回答
28086 浏览
提问于 2025-04-16 09:35

我想用SQLalchemy来做一个左外连接,并且过滤掉在连接表中有匹配的行

我正在发送推送通知,所以我有一个Notification表。这也意味着我有一个ExpiredDeviceId表,用来存储那些不再有效的设备ID。(我不想直接删除受影响的通知,因为用户可能会重新安装应用,这样通知就应该根据苹果的文档恢复。)

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

注意:每个设备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)这个条件来实现,但这看起来效率要低很多。

1 个回答

16

你需要把过期的设备ID放在一个元组里吗?如果不需要(也就是说,你只关心活跃的设备ID),那你是不是可以直接这样做:

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

撰写回答