【问题标题】:Filtering on a left join in SQLalchemy在 SQLalchemy 中过滤左连接
【发布时间】:2011-06-05 12:09:56
【问题描述】:

我想使用 SQLalchemy 执行左外连接并过滤掉连接表中匹配的行

我正在发送推送通知,所以我有一个Notification 表。这意味着我还有一个 ExpiredDeviceId 表来存储不再有效的 device_id。 (我不想只删除受影响的通知,因为用户以后可能会重新安装应用程序,此时通知应根据 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) 子句来做到这一点,但这似乎效率较低。

【问题讨论】:

    标签: python sql join sqlalchemy


    【解决方案1】:

    您需要在元组中拉回 ExpiredDeviceId 吗?如果您不这样做(即您只关心实时 device_ids),那么您就不能这样做:

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

    【讨论】:

    • 你是对的。我错误地认为 ExpiredDeviceId 实际上是一个对象引用,并且如果没有匹配的行,ExpiredDeviceId 本身就是无。然而,它实际上是一个类(表)名称,并且表达式被编译为有效的 SQL。 (请注意,对于我的问题的措辞,我需要检查它是否IS None,这也有效。)
    • 啊,好点,已经编辑了我的代码摘录以避免混淆
    • ExpiredDeviceId.expiration_time is None 不起作用 - 在传递给 .filter() 之前,它总是会评估为 False,从而导致意外行为(如果您希望像读取 SQL 一样读取查询,则会出现意外)。使用==
    猜你喜欢
    • 2016-05-08
    • 2013-01-19
    • 2022-08-24
    • 2019-08-10
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 2018-02-11
    • 1970-01-01
    相关资源
    最近更新 更多