SQL "между" не включительно
У меня есть такой запрос:
SELECT * FROM Cases WHERE created_at BETWEEN '2013-05-01' AND '2013-05-01'
Но это не дает никаких результатов, даже если есть данные о первом.
created_at
выглядит как 2013-05-01 22:25:19
, я подозреваю, что это связано с временем? Как это можно решить?
Он отлично работает, если я делаю более крупные диапазоны дат, но он должен (включительно) работать с одной датой тоже.
Ответы
Ответ 1
Это включено. Вы сравниваете дату и время. Вторая дата интерпретируется как полночь, когда начинается день.
Один из способов исправить это:
SELECT *
FROM Cases
WHERE cast(created_at as date) BETWEEN '2013-05-01' AND '2013-05-01'
Еще один способ исправить это с помощью явных двоичных сравнений
SELECT *
FROM Cases
WHERE created_at >= '2013-05-01' AND created_at < '2013-05-02'
Аарон Бертран имеет длинную запись в блоге о датах (здесь), где он обсуждает эту и другие проблемы с датами.
Ответ 2
Предполагалось, что вторая ссылка на дату в синтаксисе BETWEEN
магически считается "концом дня", но это неверно.
то есть. это ожидалось:
SELECT * FROM Cases
WHERE created_at BETWEEN the beginning of '2013-05-01' AND the end of '2013-05-01'
но что действительно происходит, это:
SELECT * FROM Cases
WHERE created_at BETWEEN '2013-05-01 00:00:00+00000' AND '2013-05-01 00:00:00+00000'
Это становится эквивалентом:
SELECT * FROM Cases WHERE created_at = '2013-05-01 00:00:00+00000'
Проблема заключается в одном из представлений/ожиданий о BETWEEN
, которые делает, включают BOTH более низкое значение и верхние значения в диапазоне, но не волшебным образом создает введите "начало" или "конец".
BETWEEN
следует избегать при фильтрации по диапазонам дат.
Всегда используйте >= AND <
вместо
SELECT * FROM Cases
WHERE (created_at >= '20130501' AND created_at < '20130502')
круглые скобки необязательны здесь, но могут иметь значение в более сложных запросах.
Ответ 3
Вам нужно сделать один из этих двух вариантов:
- Включите компонент времени в ваше условие
between
: ... where created_at between '2013-05-01 00:00:00' and '2013-05-01 23:59:59'
(не рекомендуется... см. последний абзац)
- Используйте неравенства вместо
between
. Обратите внимание, что тогда вам придется добавить один день ко второму значению: ... where (created_at >= '2013-05-01' and created_at < '2013-05-02')
Мои личные предпочтения - второй вариант. Кроме того, Аарон Бертран имеет очень четкое объяснение того, почему его следует использовать.
Ответ 4
Просто используйте метку времени в качестве даты:
SELECT * FROM Cases WHERE date(created_at)='2013-05-01'
Ответ 5
Я считаю, что лучшим решением для сравнения поля даты и времени с полем даты является следующее:
DECLARE @StartDate DATE = '5/1/2013',
@EndDate DATE = '5/1/2013'
SELECT *
FROM cases
WHERE Datediff(day, created_at, @StartDate) <= 0
AND Datediff(day, created_at, @EndDate) >= 0
Это эквивалентно инклюзивному утверждению между, поскольку оно включает как дату начала и окончания, так и те, которые попадают между ними.
Ответ 6
cast(created_at as date)
Это будет работать только в 2008 году и более поздних версиях SQL Server
Если вы используете более старую версию, используйте
convert(varchar, created_at, 101)
Ответ 7
Вы можете использовать функцию date()
которая извлечет дату из даты и времени и выдаст вам результат как включающую дату:
SELECT * FROM Cases WHERE date(created_at)='2013-05-01' AND '2013-05-01'
Ответ 8
В качестве альтернативы:
SELECT *
FROM Cases
WHERE convert(varchar, created_at, 120) Like '2013-05-01%'