我遇到了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
?
答案 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