【问题标题】:Selecting users who were not sent newsletter选择未发送时事通讯的用户
【发布时间】:2016-07-12 21:42:41
【问题描述】:

尝试创建查询以选择在批处理超时时未通过电子邮件发送简报的用户。 mail_log 表从 3 个不同的邮件列表中捕获条目,并维护过去 4-5 周的日志 - 换句话说,每个订阅者应该有多个日志条目。

我想选择在发送时批处理超时时未收到电子邮件的所有订阅者。

mail_log
+--------+------------+-------------+------------+---------+
| log_id | send_date  | location_id | mailing_id | list_id |
+--------+------------+-------------+------------+---------+
location_id is which mailing list
mailing_id is the specific newsletter
list_id is the subscriber's id in the mailing list

mail_list 
+---------+-------+-------+-------+
| list_id | fname | lname | email |
+---------+-------+-------+-------+

我试过这个查询:

SELECT mail_list.*
FROM mail_list
LEFT JOIN mail_log ON mail_log.list_id = mail_list.list_id
WHERE mail_log.send_date = '2016-07-12'
AND mail_log.location_id = '2'
AND mail_log.list_id IS NULL`

查询返回 0 个结果,但成功的查询应该返回大约 700 个结果。

【问题讨论】:

  • 是的,Dangers of Not In 的无耻广告机会
  • 你还必须选择mail_log.* --
  • 将 WHERE 更改为 AND。将最后的 AND 更改为 WHERE
  • @Zak 为什么他需要选择它们?所有这些列都是NULL

标签: mysql


【解决方案1】:

当你使用LEFT JOIN时,你必须把对子表的限制放到ON子句中。否则,当您测试这些字段时,您只会匹配非 NULL 行,这与 AND mail_log.list_id IS NULL 测试相矛盾。

SELECT mail_list.*
FROM mail_list
LEFT JOIN mail_log ON mail_log.list_id = mail_list.list_id
    AND mail_log.send_date = '2016-07-12'
    AND mail_log.location_id = '2'
WHERE mail_log.list_id IS NULL

【讨论】:

  • 谢谢。在我发布之后,我发现这个查询也有效。 SELECT * FROM mail_list WHERE list_id NOT IN (SELECT list_id FROM mail_log WHERE mailing_id='216') 关于哪个查询更好的任何反馈?
  • 普通连接往往比WHERE IN (SELECT ...) 更好,因为它们更好地使用索引。我不知道WHERE NOT IN 的相对性能。对它们进行基准测试。
【解决方案2】:

SELECT * FROM mail_list WHERE list_id NOT IN (SELECT list_id FROM mail_log WHERE mailing_id='216')

更糟糕,因为使用 NOT IN,不会使用索引。带有左连接的查询可以使用 list_id、send_date 和 location_id 作为连接的可能索引。

【讨论】:

    猜你喜欢
    • 2012-02-25
    • 2012-01-07
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    • 2012-03-08
    • 2015-09-24
    • 2013-12-06
    • 2012-06-25
    相关资源
    最近更新 更多