意外结果 - 基于日期比较的MySQL SELECT

时间:2012-02-06 12:21:45

标签: mysql sql date select

我遇到了MySQL选择查询的一些意外行为。我正在运行查询:

SELECT `refno`, `subdomain`, `toplevels`, `renew_until`, `expiry_date`, 
(YEAR(`renew_until`) - YEAR(`expiry_date`)) AS `renew_for` FROM `testing_names` 
WHERE `expiry_date` >= DATE(NOW()) AND `renew_for` >= 0

返回(按预期):

|  refno  |  subdomain  |  toplevels  |  renew_until  |  expiry_date  |  renew_for  |
|-----------------------------------------------------------------------------------|
|  5      |  domain1    |  com        |  2014-02-02   |  2014-02-02   |  0          |
|  45     |  domain2    |  net        |  2014-01-27   |  2013-01-27   |  1          |

但是,以下查询(请注意renew_for上的不同比较)会返回一个空集:

SELECT `refno`, `subdomain`, `toplevels`, `renew_until`, `expiry_date`, 
(YEAR(`renew_until`) - YEAR(`expiry_date`)) AS `renew_for` FROM `testing_names` 
WHERE `expiry_date` >= DATE(NOW()) AND `renew_for` > 0

在这种情况下,我期待第45行;我的查询有什么问题?我是否以正确的方式使用renew_for

2 个答案:

答案 0 :(得分:2)

其他RDBMS不允许使用以下语法:WHERE子句中不应提供列别名。
MySQL does it's own thing though结果不稳定:

  

标准SQL不允许您引用WHERE子句中的列别名。强制执行此限制是因为执行WHERE代码时,可能尚未确定列值。

因此,将WHERE条件更改为此

WHERE `expiry_date` >= DATE(NOW()) AND (YEAR(`renew_until`) - YEAR(`expiry_date`)) > 0

或使用派生表

SELECT *
FROM
   (
    SELECT 
        `refno`, `subdomain`, `toplevels`, `renew_until`, `expiry_date`, 
         (YEAR(`renew_until`) - YEAR(`expiry_date`)) AS `renew_for`
    FROM `testing_names` 
    ) T
WHERE `expiry_date` >= DATE(NOW()) AND `renew_for` > 0

答案 1 :(得分:1)

从进一步看,似乎使用HAVING将使用最简单的语法在MySQL中完成工作;但据我所知,这是MySQL做自己事情的另一个例子(WHERE vs HAVING);因此,如果优先考虑接近SQL标准,@ gbn的解决方案可能是最好的。

使用HAVING

SELECT `refno`, `subdomain`, `toplevels`, `renew_until`, `expiry_date`,
(YEAR(`renew_until`) - YEAR(`expiry_date`)) AS `renew_for` FROM `testing_names`
WHERE `expiry_date` >= DATE(NOW()) HAVING `renew_for` > 0