繁体   English   中英

MySql在两个表之间交叉联接并与另一个匹配

[英]MySql CROSS JOIN between two tables and match with another

首先,抱歉我的英语不好。 我的情况如下:

我正在开发一种将通知消息发送给许多用户的通知服务。 我在MySql上有以下3个表

users(user_id)

notifications(notification_id, notification)

notifications_log(notification_log_id, notification_id, user_id)

每次用户阅读通知时,我都会在notifications_log表上插入一条记录,例如。 具有user_id = 2 John用户读取了具有notification_id =3的通知:“这是一个通知”,然后我在notifications_lo user_id = 2notification_id = 3 notifications_lo g上插入了一条记录。

一切正常,但我必须创建一个查询来获取未插入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表相对应的表。 创建通知后,将其放置在每个用户的收件箱表中。 这样,您可以在单个表上执行简单的查询来确定每个用户的未读通知,而不是潜在地执行cross join联接的可怕问题。

同样,也可以选择一个单独的notification_delivery表,而不是具有“ read”标志的收件箱和日志表。 这也将允许有针对性的通知,以及批量交付给所有用户。

似乎您走在正确的轨道上,但应该只在第二行到最后一行将user_id更改为notification_id

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 n.notification_id NOT IN (SELECT nl.notification_id FROM notifications_log as nl)
AND u.user_id = 1 /* test with user 1 */

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM