我正在尝试为没有仅在3个月内下订单的帐户的客户的电子邮件创建续集查询。如果我进行查询
SELECT checkouts.email
FROM orders, checkouts
WHERE orders.id = checkouts.order_id AND orders.user_id is NULL
AND orders.created_at < CURDATE() - INTERVAL 3 MONTH
我收到的所有电子邮件均来自过去3个月内没有帐户的订单,但它没有考虑过去3个月内没有来自相同电子邮件的帐户的订单sql查询电子邮件列表。因此,我想使用MINUS运算符从最近的订单中减去所有电子邮件。当我尝试这个时,我收到一个错误:
SELECT checkouts.email
FROM orders, checkouts
WHERE orders.id = checkouts.order_id AND orders.user_id is NULL
AND orders.created_at < CURDATE() - INTERVAL 3 MONTH
MINUS
SELECT checkouts.email
FROM orders, checkouts
WHERE orders.id = checkouts.order_id AND orders.user_id is NULL
AND orders.created_at > CURDATE() - INTERVAL 3 MONTH
如果我使用UNION而不是MINUS运行相同的查询,它可以正常工作,并且无论日期如何,基本上都可以从没有帐户的订单中提供所有电子邮件。
为什么UNION工作而不是MINUS?我如何修复此查询,以便我可以让MINUS工作?
答案 0 :(得分:1)
尝试使用此构造(可能有更好的执行计划以及其他说法):
SELECT checkouts.email
FROM orders, checkouts
WHERE orders.id = checkouts.order_id AND orders.user_id is NULL
AND orders.created_at < CURDATE() - INTERVAL 3 MONTH
AND checkouts.email NOT IN (
SELECT checkouts.email
FROM orders, checkouts
WHERE orders.id = checkouts.order_id AND orders.user_id is NULL
AND orders.created_at > CURDATE() - INTERVAL 3 MONTH
)
您可能还想为checkouts.email IS NULL
添加处理,因为那不会是非(如果该措辞有意义),因为NULL永远不会=或&lt;&gt;任何事情。
SELECT checkouts.email
FROM orders, checkouts
WHERE orders.id = checkouts.order_id AND orders.user_id is NULL
AND orders.created_at < CURDATE() - INTERVAL 3 MONTH
AND (
checkouts.email IS NULL
OR
checkouts.email NOT IN (
SELECT checkouts.email
FROM orders, checkouts
WHERE orders.id = checkouts.order_id AND orders.user_id is NULL
AND orders.created_at > CURDATE() - INTERVAL 3 MONTH
)
)
您可能还会考虑更简单:
SELECT checkouts.email, MAX(orders.created_at)
FROM orders, checkouts
WHERE orders.id = checkouts.order_id AND orders.user_id is NULL
GROUP BY checkouts.email
HAVING MAX(orders.created_at) < CURDATE() - INTERVAL 3 MONTH
答案 1 :(得分:0)
MySQL不进行日期算术...你必须使用DATE_ADD()或DATE_SUB(),例如
DATE_ADD( CURDATE(), INTERVAL 3 MONTH )
DATE_SUB( CURDATE(), INTERVAL 3 MONTH )
此外,日期可以是PITA。如果created_at包含时间,则需要确保获得DATE ONLY部分,因此它意味着12:00:00 AM(使用CURDATE()函数即可)。但是,与您的结束日期相似...如果您的结束日期是2012年2月24日,但想要包括截至2012年2月24日晚上11:59:59,那么您最好不要超过一天... ex: &LT; 2012年2月25日