Включает ли «между» MS SQL Server границы диапазона? - PullRequest
222 голосов
/ 15 апреля 2009

Например, может

SELECT foo
FROM bar
WHERE foo BETWEEN 5 AND 10

выберите 5 и 10 или они исключены из диапазона?

Ответы [ 8 ]

248 голосов
/ 15 апреля 2009

Да, но будьте осторожны при использовании между датами.

BETWEEN '20090101' AND '20090131'

действительно интерпретируется как 12:00 или

BETWEEN '20090101 00:00:00' AND '20090131 00:00:00'

поэтому пропустит все, что произошло в день 31 января. В этом случае вам придется использовать:

myDate >= '20090101 00:00:00' AND myDate < '20090201 00:00:00'  --CORRECT!

или

BETWEEN '20090101 00:00:00' AND '20090131 23:59:59' --WRONG! (see update!)

ОБНОВЛЕНИЕ : Вполне возможно, что записи будут созданы в течение последней секунды дня с датой и временем 20090101 23:59:59.997 !!

По этой причине подход BETWEEN (firstday) AND (lastday 23:59:59) не рекомендуется.

Вместо этого используйте подход myDate >= (firstday) AND myDate < (Lastday+1).

Хорошая статья по этому вопросу здесь .

248 голосов
/ 15 апреля 2009

Между оператором включительно.

Из Книг Онлайн:

МЕЖДУ возвращает ИСТИНА, если значение test_expression больше чем или равно значению begin_expression и меньше или равно значению end_expression.

Предостережение DateTime

NB. С DateTimes вы должны быть осторожны; если указана только дата, значение берется по состоянию на полночь этого дня; во избежание пропуска времени в вашей конечной дате или повторения захвата данных следующего дня в полночь в нескольких диапазонах, ваша конечная дата должна быть за 3 миллисекунды до полуночи следующего дня после вашей даты. 3 миллисекунды, потому что любое значение меньше этого значения будет округлено до полуночи следующего дня.

например. чтобы получить все значения в течение июня 2016 года, вам нужно выполнить:

where myDateTime between '20160601' and DATEADD(millisecond, -3, '20160701')

1020 * т.е. *

where myDateTime between '20160601 00:00:00.000' and '20160630 23:59:59.997'

datetime2 и datetimeoffset

Вычитание 3 мс из даты сделает вас уязвимыми для пропущенных строк в окне 3 мс. Правильное решение также самое простое:

where myDateTime >= '20160601' AND myDateTime < '20160701'
16 голосов
/ 30 июля 2010

Реальный пример из SQL Server 2008.

Исходные данные:

ID    Start
1     2010-04-30 00:00:01.000
2     2010-04-02 00:00:00.000
3     2010-05-01 00:00:00.000
4     2010-07-31 00:00:00.000

Запрос:

SELECT
    *
FROM
    tbl
WHERE
    Start BETWEEN '2010-04-01 00:00:00' AND '2010-05-01 00:00:00'

Результаты:

ID    Start
1     2010-04-30 00:00:01.000
2     2010-04-02 00:00:00.000

alt text

13 голосов
/ 26 декабря 2011

, если вы нажмете это, и на самом деле не хотите пытаться обработать добавление дня в коде, тогда позвольте БД сделать это ..

myDate >= '20090101 00:00:00' AND myDate < DATEADD(day,1,'20090101 00:00:00')

Если вы включите часть времени: убедитесь, что она относится к полуночи. В противном случае вы можете просто пропустить время:

myDate >= '20090101' AND myDate < DATEADD(day,1,'20090101')

и не переживай.

12 голосов
/ 15 апреля 2009

МЕЖДУ (Transact-SQL)

Указывает ( n ) ( включительно ) диапазон для проверки.

test_expression [ NOT ] BETWEEN begin_expression AND end_expression

Аргументы

test_expression

Является ли выражение для проверки в диапазоне, определенном begin_expression и end_expression. test_expression должен быть того же типа данных, что и оба begin_expression и end_expression.

NOT

Указывает, что результат предиката должен быть отменен.

begin_expression

Любое допустимое выражение. begin_expression должно быть одинаковыми данными введите как test_expression и end_expression.

end_expression

Любое допустимое выражение. end_expression должно быть одинаковыми данными введите как test_expression и begin_expression.

AND

Действует как заполнитель, который указывает, что test_expression должно быть в диапазоне, указанном begin_expression и end_expression.

Примечания

Чтобы указать эксклюзивный диапазон, используйте больше чем (>) и меньше чем операторы (<). Если какой-либо вклад в МЕЖДУ или НЕ МЕЖДУ предикатом является NULL, результат НЕИЗВЕСТНЫЙ. </p>

Значение результата

МЕЖДУ возвращает ИСТИНА, если значение test_expression больше чем или равно значению begin_expression и меньше или равно значению end_expression.

NOT BETWEEN возвращает TRUE, если значение test_expression меньше чем значение begin_expression или больше чем значение end_expression.

3 голосов
/ 30 января 2014

Если тип данных столбца - datetime, вы можете сделать это следующим образом, чтобы исключить время из datetime и сравнить только диапазон дат.

where cast(getdate() as date) between cast(loginTime as date) and cast(logoutTime as date)
0 голосов
/ 27 февраля 2017

Включает границы.

declare @startDate date = cast('15-NOV-2016' as date) 
declare @endDate date = cast('30-NOV-2016' as date)
create table #test (c1 date)
insert into #test values(cast('15-NOV-2016' as date))
insert into #test values(cast('20-NOV-2016' as date))
insert into #test values(cast('30-NOV-2016' as date))
select * from #test where c1 between @startDate and @endDate
drop table #test
RESULT    c1
2016-11-15
2016-11-20
2016-11-30


declare @r1 int  = 10
declare @r2 int  = 15
create table #test1 (c1 int)
insert into #test1 values(10)
insert into #test1 values(15)
insert into #test1 values(11)
select * from #test1 where c1 between @r1 and @r2
drop table #test1
RESULT c1
10
11
15
0 голосов
/ 24 марта 2015

Я всегда использовал это:

ГДЕ myDate МЕЖДУ startDate И (endDate + 1)

...