MySQL联接/子查询,其中结果由外部表的多个值过滤

时间:2018-12-28 14:48:20

标签: mysql

我有两个表:

  • 用户
  • user_action

user_action表具有以下属性:

  • id
  • user_id
  • 类型
  • 时间戳

我有两种不同类型的动作:

  • 打开的邮件
  • 收到的消息

现在我的问题是:如何进行查询,以使上个月内打开过邮件的所有用户都消失,而将最近两天内收到消息的所有用户排除在外?

我认为可以通过某种形式的联接然后在子查询中使用WHERE NOT IN来完成,但这听起来并不十分有效,所以我想知道是否有更好的方法。

1 个答案:

答案 0 :(得分:1)

我通常倾向于使用JOIN而不是EXIST / NOT EXIST子查询。

这是一种使用自我LEFT JOIN的方法:

SELECT DISTINCT
    user_id
FROM
    user_action ua
    LEFT JOIN ua2 
        ON  ua2.user_id = ua.userid
        AND ua2.type = 'received message'
        AND ua2.timestamp > CURRENT_TIMESTAMP() - INTERVAL 2 DAY
WHERE 
    ua.type = 'opened message'
    AND ua.timestamp > CURRENT_TIMESTAMP() - INTERVAL 1 MONTH
    AND ua2.user_id IS NULL

详细信息:

  • ua1使用WHERE子句搜索上个月打开过邮件的用户
  • LEFT JOIN ua2选择在最近两天内尝试查找同一用户的已接收邮件
  • WHERE ... ua2.user_id IS NULL删除发生此类消息(即LEFT JOIN成功的记录)
  • SELECT DISTINCT避免了给定用户在过去一个月内收到多个消息的情况下重复的输出行