首页 > 解决方案 > 如何从有条件的数据库中获取行 - 另一个表中存在另一个?

问题描述

我有两张桌子notificationsarchived_notifications.

通知

id | title | caption | user_id

存档通知

notification_id | user_id

如果我想从notifications表中获取表中没有行的行,archived_notificationsnotification_id = notification.id | user_id = notification.user_id.

现在我有一些这样的

cursor.execute("SELECT * FROM notifications AS n WHERE "
                   "({}=%s AND (SELECT COUNT(*) FROM archvies WHERE {}=n.id AND {}=%s) = 0) "
                   "OR "
                   "({}=%s AND (SELECT COUNT(*) FROM archvies WHERE {}=n.id AND {}=%s) = 0) "
                   "ORDER by id DESC LIMIT %s OFFSET %s"
                   .format(Keys.USER_ID, Keys.NOTIFICATION_ID, Keys.USER_ID, Keys.DIRECTION, Keys.NOTIFICATION_ID,
                           Keys.USER_ID),
                   [str(user_id), str(user_id), NotificationsClasses.GLOBAL, str(user_id), int(limit), int(offset)])

标签: sqlpostgresqlpsycopg2

解决方案


通常,您可以使用NOT IN、NOT EXISTS 和 LEFT JOIN子句中的任何一个。具体来说,您似乎还有许多其他不清楚的条件,例如来自未知Keys变量的列名的方向处理和字符串格式。

下面显示了NOT EXISTS尝试翻译当前代码的选项。根据实际需要调整:

sql = '''SELECT * FROM notifications AS n 
         WHERE n.user_id = %s
           AND NOT EXISTS
              (SELECT 1 FROM archives a
               WHERE a.user_id = %s
                 AND n.id = a.notification_id)
         ORDER by n.id DESC 
         LIMIT %s 
         OFFSET %s
      '''

cursor.execute(sql, [str(user_id), NotificationsClasses.GLOBAL, int(limit), int(offset)])

推荐阅读