Проблема MySQL между не работает с отметками времени Unix

В настоящее время я храню даты в виде временных меток Unix в столбце INT (10) в версии mysql 4.0.8 db (движок MyISAM).

Я запрашиваю эти даты, чтобы извлечь записи между диапазоном дат, используя следующий SQL:

$sql = "SELECT `users`.`real_name`, `users`.`user_value`, `clients`.`client_name`, `clients`.`client_stars`, `timing`.`start_date`, `timing`.`end_date`, `projects`.`project_name`
    from timing
    LEFT JOIN users on (users.id = timing.user_id)
    LEFT JOIN clients on (clients.id = timing.client_id)
    LEFT JOIN projects on (projects.project_id = timing.project_id)
    WHERE start_date BETWEEN :start_date AND :end_date";

Я использую PDO, поэтому параметры.

Я на 100% уверен, что переменные :start_date и :end_date верны во всех случаях, поскольку я их проверял. Также start_date не является двусмысленным, и нет никаких предупреждений/уведомлений относительно этого запроса.

Моя проблема в том, что я не получаю ожидаемые строки. Если я запрашиваю строки между полуночью 2013/11/14 и полуночью 2013/11/15, ожидание ТОЛЬКО результатов от 14-го числа. Впрочем, ряды с 15-го тоже пройдены — но не все.

Я также только что проверил между 1384473600 и 1384473600, то есть между сегодняшней полночью и сегодняшней полночью (как в той же метке времени).

Возвращаемые строки должны быть равны 0, однако он вернул все строки с сегодняшнего дня (например, первая возвращенная строка имеет значение start_date 1384524193)!

Я что-то пропустил в том, как работает оператор between в mySQL? Как он может возвращать строки, когда min и max совпадают?

Я тестировал и тестировал, и почти каждый раз, когда я делаю запрос, возвращаются строки, которые ВЫШЕ указанного между потолком.

Что происходит не так?


person Jake Whiteley    schedule 15.11.2013    source источник
comment
вы пробовали это: WHERE start_date >= :start_date AND start_data <= :end_date ?   -  person Latheesan    schedule 15.11.2013


Ответы (2)


BETWEEN — общеизвестно плохой способ сопоставления дат и временных меток, потому что он включает оба конца диапазона.

Это может работать лучше для вас

    WHERE start_date >= :start_date
      AND start_date <  :end_date + 86400

Магическое число 86400 — это количество секунд в сутках. При этом выбираются все значения start_date между полуночью по параметру :start_date включительно, а затем исключаются все значения в полночь или после полуночи на следующий день после даты :end. Если бы вы использовали настоящие временные метки, вы могли бы сказать + INTERVAL 1 DAY вместо + 86400.

person O. Jones    schedule 15.11.2013
comment
Я пытался использовать этот подход, и, как ни странно, я все еще получаю те же результаты! Я только что попробовал диапазон 86400 секунд, заканчивающийся в полночь 14-го числа этого месяца, и я все еще получаю результаты за 14-е число. Я отправил start_date 138430080 и конечную дату 1384387200, и одна из возвращенных строк была 1384525509 — совершенно очевидно, что это не ‹= 1384387200. - person Jake Whiteley; 15.11.2013

Хотя я не знаю почему, когда я изменил логику, это сработало отлично.

WHERE timing.start_date < :end_date 
AND timing.start_date >= :start_date

Однако это не сработало и вернуло те же ошибочные результаты.

WHERE start_date >= :start_date
AND start_date <  :end_date

Кто-нибудь может объяснить, почему?

person Jake Whiteley    schedule 15.11.2013
comment
Убедитесь, что start_date и end_date имеют одинаковый формат времени! - person K3rnel31; 15.11.2013