ГДЕ возвращает слишком много строк для данных НЕ МЕЖДУ двумя датами

#mysql #datetime

#mysql #дата и время

Вопрос:

Я хочу вернуть данные, которые не находятся между текущей датой и последними 7 днями.

Мой оператор SELECT отображается нормально, но он также возвращает данные текущего дня.

 SELECT
    customer.id AS id,
    customer.customer_id AS customer_id,
    customer.name AS name,
    customer.phone1 AS phone1,
    customer.location_area AS location_area,
    sales.post_date AS post_date 
FROM 
    sales
INNER JOIN 
    customer
ON 
    sales.customer_id = customer.customer_id
WHERE 
    post_date 
NOT BETWEEN 
   CAST( DATE_SUB(NOW(), INTERVAL 7 DAY) AS DATE )
AND 
   CAST( NOW() AS DATE )
ORDER BY 
   sales.id 
DESC
LIMIT 30
  

Пожалуйста, обратите внимание, что поле customer_id, используемое в предложении ON, не является первичным ключом ни в одной из двух таблиц, на которые ссылаются.

Чего может не хватать в моем запросе?

Комментарии:

1. очевидный, но необходимый вопрос — является ли «post_date» полем даты и времени (а не varchar или чем-то еще)? Если нет, вам может потребоваться привести его перед выполнением сравнения

2. @ADyson, поле ‘post_date’ — это поле даты и времени

Ответ №1:

Обычно эта проблема связана с путаницей в отношении различных значений DATE типов данных, с одной стороны, и TIMESTAMP / или DATETIME типов данных, с другой.

Допустим NOW() , есть 1-April-2017 09:35 . И, допустим, у вас есть строка в вашей sales таблице со post_date значением 1-April-2017 08:20 . Допустим, ваш post_date столбец имеет тип данных DATETIME .

Тогда ваше предложение WHERE выглядит следующим образом после применения значений.

 WHERE '2017-04-01 08:20' NOT BETWEEN CAST( '2017-03-25 09:35' AS DATE )
                                 AND CAST( '2017-04-01 09:35' AS DATE )
  

Применяя CAST операции, мы получаем.

 WHERE '2017-04-01 08:20' NOT BETWEEN '2017-03-25'
                                 AND '2017-04-01'
  

Наконец, при сравнении DATETIME или TIMESTAMP со DATE значением DATE значение интерпретируется как имеющее время полуночи. Итак, ваш запрос выглядит следующим образом:

 WHERE '2017-04-01 08:20' NOT BETWEEN '2017-03-25 00:00:00'
                                 AND '2017-04-01 00:00:00'
  

И, угадайте, что? '2017-04-01 08:20' после '2017-04-01 00:00:00' .

Что вам нужно, так это:

 WHERE 
 NOT (
            post_date >= CURDATE() - INTERVAL 7 DAY --on or after midnight 2016-3-25
        AND post_date <  CURDATE()   INTERVAL 1 DAY --before midnight 2016-04-02
     )
  

Пожалуйста, обратите внимание, что это выражение охватывает всего восемь дней.

Вы не можете использовать BETWEEN для такого сравнения, потому что вам нужен < конец диапазона, и BETWEEN использует <= для концов всех его диапазонов.

Кроме того, CURDATE() его гораздо легче читать, чем CAST(NOW() AS DATE) .