【问题标题】:Selecting users from one table when not in the other当不在另一个表中时从一个表中选择用户
【发布时间】:2012-03-22 02:04:17
【问题描述】:

我有一个查询,从一个表中选择用户的注册日期。

SELECT DATE(registered)
FROM users
WHERE user_id= ".$currentUser."
ORDER BY registered ASC
LIMIT 1

我需要通过加入另一个表来修改原始查询,以确保用户不存在于第二个表(“访问”)中,其中成员 ID 低于特定值且访问日期低于特定日期。

LEFT JOIN access ON (users.user_id = access.user_id)
WHERE access.user_id < 500
AND access.date ... after March 1, 2012

不知道如何将这两者结合在一起。

【问题讨论】:

    标签: mysql sql anti-join


    【解决方案1】:

    你需要把整个条件放在join中,否则你会有效地把它变成一个inner join:

    ...
    LEFT JOIN access ON (
      users.user_id = access.user_id
      AND access.user_id < 500
      AND access.date >= '20120301'
    )
    WHERE access.user_id is null
    ...
    

    【讨论】:

    • "当不在另一个表中时从一个表" = 反连接。
    • @onedaywhen:是的,这就是您使用左连接并检查空值时所做的事情。
    • @onedaywhen:如果你幸运的话,查询规划器会将not exists() 变成左连接,因为它更有效。
    • “是的,这就是你使用左连接并检查空值时所做的事情”——我想说的是反过来:这个概念是存在量化,关系运算符是半差分(又名反连接)和 SQL 中的实现通常有大约七种不同的方式。就我个人而言,我避免使用像瘟疫这样的空值,而外连接是专门为产品空值而设计的。
    • “如果你幸运的话,查询规划器会将 [您最喜欢的大约七个候选查询的选择] 变成 [优化器最喜欢的大约七个候选查询的选择]”——我期待 DBMS .
    【解决方案2】:

    您可以使用相关子查询,例如:

      SELECT DATE(u.registered)
        FROM users u
       WHERE u.user_id = ".$currentUser."
    
         AND NOT EXISTS (
                 SELECT 1 
                   FROM access a 
                  WHERE u.user_id = a.user_id
                    AND a.user_id < 500
                    AND a.date > DATE '2012-03-01')
    
    ORDER BY registered ASC 
    LIMIT 1;
    

    一些注意事项:
    即使access 表中没有匹配的行,您仍然可以返回一行。
    您可能知道...ASC 是默认排序顺序,因此您无需输入。

    【讨论】:

    • 太棒了!我只是想到了一些事情。我确实需要日期为 a.date > DATE '2012-03-01' 但它也不能是今天的日期...我可以添加 AND a.date != NOW() 吗?
    • 是的,在子查询中再添加一行:AND a.date &lt;&gt; CURDATE()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多