首先抱歉我的英语不好。我的场景如下:
我正在开发一个向许多用户发送通知消息的通知服务。我在 MySql 上有以下 3 个表
用户(user_id)
通知(notification_id, notification)
notifications_log(notification_log_id, notification_id, user_id)
每次用户阅读通知时,我都会在 notifications_log 表中插入一条记录,例如。 user_id = 2
的 John 用户阅读了 notification_id =3
的通知:“这是一个通知”,然后我在 notifications_lo
上插入一条记录g 与 user_id = 2
和 notification_id = 3
。
一切正常,但我必须创建一个查询来获取所有未插入 notifications_log 的用户的所有通知。我拥有的是:
SELECT u.user_id, n.notification_id, n.notification, nl.notification_log_id
FROM users as u
LEFT JOIN notifications_log as nl ON nl.user_id = u.user_id
CROSS JOIN notifications as n
WHERE u.user_id NOT IN (SELECT nl.user_id FROM notifications_log as nl)
AND u.user_id = 1 /* test with user 1 */
如果用户1的notifications_log表没有记录,查询结果显示给我
user_id | notification | notification_id | notification_log_id
------------------------------------------------------------------------------
- 1 | Notification_1 | 1 | null
- 1 | Notification_2 | 2 | null
但是如果我在 notifications_log
上为用户和 notification_2 插入至少 1 条记录,那么我得到空结果,我应该得到:
user_id | notification | notification_id | notification_log_id
----------------------------------------------------------------------------
- 1 | Notification_1 | 1 | null
查询似乎将 notification_log_id 加入了另一条 notification_log_id 为空的记录...
简而言之,我需要的是从特定用户那里获取所有通知,这些通知没有插入到表 notifications_log 中
提前致谢!
最佳答案
你想要的查询可能是这个:
select n.notification_id, u.user_id
from notifications n
cross join users u
left join notifications_log nl
on n.notification_id = nl.notification_id
and nl.user_id = u.user_id
where nl.notification_log_id is null
此查询消除了您的派生表,减少了执行时间,并尽早执行交叉连接以减少正在操作的总行数。
但我建议重新考虑一下。一旦通知和用户表达到临界质量,这将创建数以百万计的行来过滤。
一个更好的主意是拥有一个 notification_inbox 表,作为您的 notifications_log 表的对应物。创建通知后,将其放入每个用户的收件箱表中。这样您就可以在单个表上执行简单的查询以确定每个用户的未读通知,而不是执行可能可怕的交叉连接
。
或者,单个 notification_delivery 表,而不是收件箱和日志表,它有一个“读取”标志。这也将允许有针对性的通知,以及向所有用户批量传送。
关于php - MySql 两个表之间的 CROSS JOIN 并与另一个表匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30363389/