Mysql 使用UNION的SQL查询是有效的,但当我用减号替换时就不起作用了
我正在尝试创建一个续集查询电子邮件的客户没有帐户,只有下订单超过3个月。如果我做这个查询Mysql 使用UNION的SQL查询是有效的,但当我用减号替换时就不起作用了,mysql,Mysql,我正在尝试创建一个续集查询电子邮件的客户没有帐户,只有下订单超过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个月
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查询电子邮件列表中相同的电子邮件。因此,我想使用减号运算符从最近的订单中减去所有电子邮件。当我尝试此操作时,会出现一个错误:
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而不是减号,那么它就可以工作了,并且基本上可以给我所有来自订单的电子邮件,而不必考虑日期
为什么工会是有效的而不是负的?如何修复此查询,以便让减号开始工作?尝试此构造,否则可能会有更好的执行计划和其他方式:
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
)
你也可以更简单地考虑:
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
MySQL不做日期运算。。。您必须使用DATE\u ADD或DATE\u SUB,例如
DATE_ADD( CURDATE(), INTERVAL 3 MONTH )
DATE_SUB( CURDATE(), INTERVAL 3 MONTH )
此外,日期可以是一个PITA。如果创建的时间包含时间,则需要确保只获取日期部分,因此它表示12:00:00 AM,这与CURDATE函数是一致的。然而,与你的结束日期相似。。。如果您的结束日期是2012年2月24日,但希望包括2012年2月24日下午11:59:59,您最好再多做不到一天。。例如:<2012年2月25日MySQL不支持减号或EXCEPTOk。那太糟糕了。你知道如何在不使用减号的情况下实现这一点吗?进行反半联接的其他方法有1个外部联接和空过滤,2个不存在,3个不存在。您的答案看起来不错,但查询仍在运行,尚未完成。我会让您知道这是否如预期的那样有效。@Zyren我会尝试将外部左连接改为子查询。有可能执行计划实际上是为第一个集合中的每一行运行该集合,而不是连接两个集合。@Zyren不幸的是,MySQL也不支持CTEs/子查询分解,因此,你也不能使用这些技术来提高它的性能或可读性:@Zyren我添加了一个更简单的结构,我认为这会非常有效。
DATE_ADD( CURDATE(), INTERVAL 3 MONTH )
DATE_SUB( CURDATE(), INTERVAL 3 MONTH )