【问题标题】:Read notifications table阅读通知表
【发布时间】:2017-10-05 00:10:33
【问题描述】:

我正在制作一个通知表。结构如下:

notifications:    
+----+------+----------------------+-----------------------------------+-----------+
| ID | user | notification         | message                           | timestamp |
+----+------+----------------------+-----------------------------------+-----------+
| 1  | 6    | Denied acceptance    | You have been denied for...       |           |
| 2  | 6    | Apreooved acceptance | You have been accepted...         |           |
| 3  | 0    | Open slots           | there are still open slots for... |           |
+----+------+----------------------+-----------------------------------+-----------+

还有一个表格,指示每个用户阅读了哪个通知

notifications_read    
+----+------+--------------+-----------+
| ID | user | notification | timestamp |
+----+------+--------------+-----------+
| 1  | 6    | 2            |           |
+----+------+--------------+-----------+

如果通知仅针对一个用户,则“通知”中的“用户”下有一个用户 ID - 如果通知针对所有人,我在用户下插入“0”。

我正在尝试从“通知”中选择未读取的行的查询。

我当前的查询不正确:

SELECT * 
FROM notifications 
WHERE id NOT IN 
    (SELECT notification 
     FROM notification_read 
     WHERE user = $id) AND user = $id OR user = 0

所以对于上表,它需要选择 id 为 1 & 3 的行

感谢您的帮助!

【问题讨论】:

  • 当通知适用于所有用户时,“未阅读”是什么意思?您是否只查找特定用户的未读通知?

标签: mysql sql


【解决方案1】:

如果您想要特定用户的未读通知,那么您就在正确的轨道上:

SELECT n.* 
FROM notifications n
WHERE n.id NOT IN (SELECT nr.notification 
                   FROM notification_read nr
                   WHERE nr.user = $id) AND
      (n.user = $id OR n.user = 0);

我认为唯一的问题是 OR 周围的逻辑括号。

你也可以用IN写这个:

SELECT n.* 
FROM notifications n
WHERE n.id NOT IN (SELECT nr.notification 
                   FROM notification_read nr
                   WHERE nr.user = $id) AND
      n.user IN (0, $id);

【讨论】:

  • 您的解决方案很有希望。我将在表格中的几种组合上对其进行测试。
【解决方案2】:
SELECT n.*
FROM notifications n
LEFT JOIN notifications_read nr ON nr.notification = n.id
WHERE
nr.id IS NULL

这将为您提供notifications_read 表中不存在的通知。

左连接将为您提供通知中的所有行,并连接来自 notifications_read 的具有通知 ID 的行。因此,当您按nr.id IS NULL 过滤时,您将返回存在于notifications 但不存在于notifications_read 中的行。

此外,LEFT JOIN 的性能会更好。

LEFT [OUTER] JOIN 可以比等效的子查询更快,因为服务器可能能够更好地优化它——这一事实并非仅针对 MySQL 服务器。 https://dev.mysql.com/doc/refman/5.7/en/rewriting-subqueries.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-20
    • 1970-01-01
    • 2015-09-11
    • 1970-01-01
    相关资源
    最近更新 更多