Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 使用UNION的SQL查询是有效的,但当我用减号替换时就不起作用了_Mysql - Fatal编程技术网

Mysql 使用UNION的SQL查询是有效的,但当我用减号替换时就不起作用了

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个月

我正在尝试创建一个续集查询电子邮件的客户没有帐户,只有下订单超过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 )