首页 > 解决方案 > MySQL 连接/子查询,其中结果由外部表的多个值过滤

问题描述

我有两张桌子:

user_action 表具有以下属性:

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

现在我的问题是:如何进行查询,以获取上个月内打开消息的所有用户,但排除过去 2 天内收到消息的所有用户?

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

标签: mysqlsqldatabasedatejoin

解决方案


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

这是一种使用 self- 的方法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 ua2optionnaly 尝试查找过去两天内同一用户收到的消息
  • WHERE ... ua2.user_id IS NULL删除发生此类消息的记录(即LEFT JOIN成功的记录)
  • SELECT DISTINCT当给定用户在上个月收到多条消息时,避免重复的输出行

推荐阅读