Неожиданный результат - MySQL SELECT на основе сравнения дат - PullRequest
1 голос
/ 06 февраля 2012

Я столкнулся с неожиданным поведением при выборе запроса 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 ]

2 голосов
/ 06 февраля 2012

Другие СУБД не разрешают этот синтаксис: псевдонимы столбцов не должны быть доступны в предложении WHERE.
MySQL, однако, работает сам по себе с ошибочными результатами:

Стандартный 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 голос
/ 06 февраля 2012

Если взглянуть дальше, кажется, что использование HAVING сделает работу в MySQL с самым простым синтаксисом;но, насколько я понимаю, это еще один случай, когда MySQL делает свое дело ( ГДЕ против 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
...