在WHERE上用“不在”和?

时间:2013-04-18 19:36:08

标签: mysql

我正在努力更好地理解“不在”中如何使用MySQL中的WHERE。

例如:

SELECT * FROM current_mailing_list 
WHERE address1 NOT IN
    (select address1 from old_mailing_list) AND
    city not in (select city from old_mailing_list);

在上面的示例中,查询的目的是列出新的邮件地址。 address1是街道地址,例如1234 N. Main St。当1234 N. Main St发生在多个城市时会发生问题,这可能发生。所以我决定添加city以使其更加独特。

我的问题是,这是按照我的预期做的吗?这意味着,它应该找到old_mailing_list AND 中不存在的街道地址(地址1),然后确保它们具有不同的city

我已完成此操作,只需使用address1:

SELECT * FROM current_mailing_list 
WHERE address1 NOT IN 
    (select address1 from old_mailing_list);

它产生了一个更大的列表(大约10倍)。所以我想在此添加city。或者我的逻辑是完全错误的还需要另一种方法吗?

3 个答案:

答案 0 :(得分:6)

您当前的查询不会返回旧地址列表中其“地址1”或“城市”出现在所有的新地址。我想你想选择他们不会一起出现的城市,如下所示:

SELECT *
FROM current_mailing_list c
WHERE NOT EXISTS
(
    SELECT 1
    FROM old_mailing_list
    WHERE
        address1 = c.address1
        AND city = c.city
)

相当字面;选择当前邮件列表中的所有内容,其中旧邮件列表中没有记录,具有相同的城市和地址1。

答案 1 :(得分:3)

要使用NOT IN,您需要在MySQL支持的同一子句中组合城市和地址(其他RDBMS不支持此方法)。正如其他人所指出的那样,你不会单独使用它们来获得理想的结果。

如果您想使用NOT IN

,请尝试此操作
SELECT * 
FROM current_mailing_list 
WHERE (address1,city) NOT IN  
   (select address1, city from old_mailing_list);

Sample SQL Fiddle Demo

我更喜欢亲自使用LEFT JOIN并检查NULL:

SELECT c.* 
FROM current_mailing_list c
    LEFT JOIN old_mailing_list o ON c.address1 = o.address1 AND c.city = o.city
WHERE o.address1 IS NULL

答案 2 :(得分:1)

如果1234 N. Main St.是旧邮件列表中的城市和新邮件列表中的城市的地址,则您的查询将排除BOTH地址。您的查询正在执行其正在执行的操作:您将在旧邮件列表中获取两者街道地址和城市 的地址。如果 显示旧邮件列表中的地址,则不会检索该地址。