MS SQL Server의 "사이"에 범위 경계가 포함됩니까?


234

예를 들어

SELECT foo
FROM bar
WHERE foo BETWEEN 5 AND 10

5와 10을 선택하거나 범위에서 제외됩니까?

답변:


258

BETWEEN 연산자가 포함됩니다.

온라인 설명서에서 :

test_expression의 값이 begin_expression의 값보다 크고 end_expression의 값보다 작거나 같으면 BETWEEN은 TRUE를 반환합니다.

날짜 / 시간주의 사항

주의 : DateTimes에서는주의해야합니다. 날짜 만 제공되면 그 날 자정을 기준으로 값이 취해집니다. 종료 날짜 내에 시간이 누락되거나 여러 범위의 자정에 다음 날 데이터 캡처가 반복되는 것을 방지하려면 종료 날짜는 현재 날짜 다음 날 자정 전 3 밀리 초 여야합니다. 이보다 작은 값과 다음 날 자정으로 올림되므로 3 밀리 초입니다.

예를 들어 2016 년 6 월 이내에 모든 값을 얻으려면 다음을 실행해야합니다.

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

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

datetime2 및 datetimeoffset

날짜에서 3ms를 빼면 3ms 창에서 누락 된 행에 취약 해집니다. 올바른 솔루션도 가장 간단한 솔루션입니다.

where myDateTime >= '20160601' AND myDateTime < '20160701'

11
BETWEEN을 사용하여 두 날짜 사이의 DateTimes를 필터링하는 경우 DateTime을 Date로 캐스트 할 수도 있습니다. 예 : CONVERT (DATE, MyDate) BETWEEN '2017-09-01'및 '2017-09-30' 날짜와 관계없는 요소
Pete

1
날짜에서 3ms를 빼려고하지 마십시오. 당신은 그 3 ms에서 항목을 그리워합니다. 그리고 당신은 또한 원하지 않는 날짜 A와 날짜 즉 쓸모없는 인덱스를 렌더링으로. 표준을 사용하십시오 . 또한, 사용하십시오 으로, IS 의존 로케일, 및 서버의에 따라 해석 될 것입니다 설정. CONVERTWHERE OrderDate >= '20160601' AND OrderDate < '20160701'yyyymmddyyyy-mm-ddmdy, dmy, ymd, ydm, myd, and dym
Ian Boyd

254

예, 그러나 날짜 사이에 사용할 때는주의하십시오.

BETWEEN '20090101' AND '20090131'

실제로 오전 12 시로 해석되거나

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

따라서 1 월 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!)

업데이트 : 날짜 시간이 늦어도 하루의 마지막 2 초 내에 레코드를 만들 수 있습니다 20090101 23:59:59.997!

이러한 이유로이 BETWEEN (firstday) AND (lastday 23:59:59)방법은 권장되지 않습니다.

myDate >= (firstday) AND myDate < (Lastday+1)대신 이 방법을 사용하십시오 .

이 문제에 대한 좋은 기사는 여기에 있습니다 .


1
문자열과 비슷한 문제 WHERE col BETWEEN 'a' AND 'z'는 예를 들어 대부분의 z 행을 제외합니다.
Martin Smith

8
이 시점은 물론 옳습니다. 날짜 시간으로 작업하는 경우 놀라운 일이 아닙니다. 그것은 BETWEEN 5 AND 10포함하지 않는 지적과 유사합니다 10.2...
Andrzej Doyle

4
CAST할 수 있는 datetime대로 DATE: CAST(DATE_TIME_COL AS DATE) BETWEEN '01/01/2009' AND '01/31/2009'.
craig

2
@craig, SQL 2008 이상을 사용하는 한 날짜 데이터 유형이 도입 된 경우에도 마찬가지입니다. 또한이 구문은 모든 단일 행에 대해 해당 값을 변환하므로 해당 필드에서 인덱스를 사용할 수 없습니다 (문제가되는 경우).
BradC

It is entirely possible to have records created within that last second of the day, with a datetime as late as 01/01/2009 23:59:59.997<-당신은 그때 사용할 수 AND '01/31/2009 23:59:59.99999999'
없었지만

16

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

대체 텍스트


솔직히 답변을받지 못했습니다. 아마 내 인터넷 제공 업체가 스크린 샷을 올렸을 때 스크린 샷을 숨겼을 것입니다.
anar khalilov

2
행이 ID = 3제외 된 이유는 무엇 입니까? 그 Start값은 BETWEEN상한 값과 같 BETWEEN으며 배타적 상한 범위가 아닌 포함 범위입니다.
Dai

결과에 대한 더 나은 답변.
Sam

13

이 코드를 누르고 실제로 하루를 코드에 추가하려고 시도하지 않으려면 DB가 그렇게하십시오.

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

시간 부분을 포함 시키면 자정을 참조해야합니다. 그렇지 않으면 단순히 시간을 생략 할 수 있습니다.

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

걱정하지 마십시오.


12

BETWEEN (Transact-SQL)

테스트 할 a ( 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으로 표시된 범위 내에 있어야 함을 나타내는 자리 표시 자 역할을합니다.

비고

배타적 범위를 지정하려면보다 큼 (>) 및보다 작음 연산자 (<)를 사용하십시오. BETWEEN 또는 NOT BETWEEN 술어에 대한 입력이 NULL 인 경우 결과는 알 수 없습니다.

결과 값

test_expression의 값이 begin_expression의 값보다 크고 end_expression의 값보다 작거나 같으면 BETWEEN은 TRUE를 반환합니다.

NOT BETWEEN은 test_expression 값이 begin_expression 값보다 작거나 end_expression 값보다 큰 경우 TRUE를 반환합니다.


3

열 데이터 유형이 datetime 인 경우 datetime에서 시간을 제거하고 날짜 범위 만 비교하기 위해 다음을 수행 할 수 있습니다.

where cast(getdate() as date) between cast(loginTime as date) and cast(logoutTime as date)

종료일에 +1을 추가하는 것보다 효과적입니다. Andrew Morton에 동의합니다. Sargable이 아닌 경우 열 데이터 형식을 변경하거나 미리 계산 된 날짜 만있는 두 번째 열을 추가하는 성능이 향상 될 수 있습니다.
Arno Peters

0

여기에는 경계가 포함됩니다.

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

-3

나는 항상 이것을 사용했다 :

startDate AND (endDate + 1) 사이의 myDate 위치

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.