왜 SQL의 BETWEEN이 반 개방이 아닌 포괄적인가?


45

세미 오픈 (또는 반 오픈 반 폐쇄 , 하프 경계 () 간격 [a,b), x간격 IFF에 속한다는 a <= x < b그들이 많은 편리한 특성을 가지고), 프로그래밍에 꽤 일반적인이다.

누구나 SQL BETWEEN이 닫힌 간격 ( [a,b])을 사용하는 이유를 설명하는 이론적 근거를 제공 할 수 있습니까 ? 이것은 esp입니다. 날짜가 불편합니다. 왜 이렇게 BETWEEN행동 했을 까요?


궁금합니다. 어떤 편리한 속성이 있습니까?
phant0m

2
포괄적이지 않은 경우 A에서 D까지의 모든 성을 어떻게 쉽게 쿼리 할 수 ​​있습니까? 또는 이름을 W에서 Z로 1에서 10 사이의 숫자의 경우 0 <n <11을 검색 할 수 있지만 문자의 경우 ASCII 숫자를 사용해야합니까? 또는 유니 코드 번호? 또한 인덱스를 사용하면 데이터를 쉽게 시작할 수 있습니다.
jqa

2
귀하의 좌절 (StartDate> = '2010-01-01'및 StartDate < '2011-01-01')이 아름답게 작동한다는 것을 이해합니다. 2010-12-31 23:59:59 '), 부피가 큰 사람과 12 월의 일 수를 알아야합니다.
Todd

1
@ phant0m [a, b) U [c, d) == [a, d). [a : int, b : int)는 정확히 ba 요소를 포함합니다. Todd의 의견은 날짜에 특히 잘 작동하는 방법을 보여줍니다 (가장 그리 웠습니다). 기본적으로, 코딩 할 때 세미 오픈 간격은 더 단순하고 사용하기 쉽고 강력합니다.
alex

최선의 답변은 BETWEEN for SQL을 처음 지정한 사람들의 객관적인 결정 문서를 참조하여 주관적인 답변이 아닌 왜라고 대답했는지 확인해야합니다.
Todd

답변:


48

포용성 BETWEEN이 반 오픈 간격보다 직관적이고 SQL 디자이너도 마찬가지 라고 생각합니다 . 예를 들어, "1에서 10 사이의 숫자를 선택하십시오"라고 말하면 대부분의 사람들은 숫자 1과 10을 포함합니다. 개방형 간격은 비대칭이기 때문에 비 개발자에게는 실제로 혼란 스럽습니다. 프로그래머가 아닌 사람이 SQL을 사용하여 간단한 쿼리를하는 경우가 종종 있으며, 반 오픈 시맨틱은 훨씬 혼란 스러웠습니다.


9
이 예에서는 10 진수 및 다른 구분 된 수량 (예 : 날짜)의 정수에 중점을 두며 그 사이의 용어는 모호합니다. 2012 년에서 2013 년 사이에 X를 수행했다고 말하면 2013 (또는 특히 2013-01-01 일)을 포함하지 않습니다
Todd

4
@Todd이 용어의 사용법은 모호합니다. 그렇기 때문에 수학자, 과학자 및 정통한 프로그래머가 자신의 의도를 "반 개방"등으로 문서화하는 것입니다. Oleski의 대답의 핵심은 SQL은 원래 프로그래머가 아닌 최종 사용자를위한 것입니다 (실제로!). 분명히 SQL 디자이너는 해당 사용자에게 가장 적합한 정의를 믿었습니다. 그러나 질문의 ​​저자가 제안한 것처럼, 반 개방은 시간 범위와 같은 범위를 다루는 데 거의 항상 좋습니다.
Basil Bourque

"저는 포괄적 인 것이 더 직관적이라고 생각합니다"는 주관적입니다. "프로그래머가 아닌 사람이 SQL을 사용하여 간단한 쿼리를하기도합니다."-프로그래머가 아닌 사람도 사양을 확인해야합니다.
Todd


이 질문은 또한 종종 " 1 에서 10 사이 의 숫자 골라라 "(물론 명백한 모호함을 피하기 위해)됩니다. 부수적으로. "1에서 10 사이의 숫자를 선택하십시오"라고 말합니다. 대부분의 사람들은 아마 1이나 10을 선택하지 않을 것입니다 . 그것은 심리학 문제에 더 가깝습니다. :) 사람들은 여전히 ​​1과 10을 유효한 선택으로 받아 들일 것입니다 (의미 적으로 부정확하더라도). 그러나 1과 10이 유효 하다고 가정하면 상황에 맞는 해석의 결과입니다 . "13과 24 사이"라고 말하면 13과 24가 포함되어 있는지 묻는 메시지가 나타납니다.
환멸

25

질문 : 왜 SQL이 BETWEEN에 포함됩니까?

답변 : SQL 언어 디자이너가 잘못된 디자인 결정을 내렸기 때문에 개발자가 BETWEEN의 4 가지 변형 (폐쇄, 준 오픈 왼쪽, 반 오픈 오른쪽 또는 오픈)을 지정할 수있는 구문을 제공하지 못했습니다. ) 선호합니다.

권장 사항 : SQL 표준이 수정되지 않는 한 날짜 / 시간에 BETWEEN을 사용하지 마십시오. 대신 DATE 범위 비교를 BETWEEN 범위의 시작 및 끝 경계에서 독립적 인 조건으로 코딩하는 습관을 가지십시오. 이것은 조금 장황하지만, 직관적 인 (따라서 버그가 적을 것임) 데이터베이스 최적화 프로그램에 명확한 조건을 작성하여 최적의 실행 계획을 결정하고 색인을 사용할 수 있습니다.

예를 들어 쿼리에서 입력 날짜 사양을 수락하고 해당 날짜에 해당하는 모든 레코드를 반환해야하는 경우 다음과 같이 코딩됩니다.

  • WHERE DATE_FIELD >= :dt AND DATE_FIELD < :dt+1

BETWEEN을 사용하여 논리를 작성하려고하면 성능 문제 및 / 또는 버그가있는 코드가 발생할 수 있습니다. 세 가지 일반적인 실수 :

1) WHERE DATE_FIELD BETWEEN :dt AND :dt+1

이것은 거의 확실히 버그입니다. 사용자는 특정 날짜의 레코드 만 볼 것으로 예상하지만 하루는 다음 날 오전 12시의 레코드가 포함 된 보고서와 함께 시작됩니다.

2) WHERE TRUNC(DATE_FIELD) = :dt

정답을 제공하지만 DATE_FIELD에 함수를 적용하면 대부분의 인덱싱 / 통계가 쓸모 없게됩니다 (그러나 DBA가 날짜 필드에 함수 기반 인덱스를 추가하여 여전히 작업 시간과 디스크 공간을 태우고 IUD에 오버 헤드를 추가하여 도움을 줄 수 있지만) 테이블 작업)

삼) WHERE EVENT_DATE BETWEEN :dt AND :dt + 1-1/24/60/60

오라클의 전문가 인 Tom Kyte는 이보다 덜 우아한 (IMO) 솔루션을 권장합니다. 불완전한 결과를 제공하는 쿼리에서 "1-1 / 24 / 06 / 60"을 찾거나 실수로 TIMESTAMP 필드에서 사용할 때까지 하루 종일 보낼 때까지 훌륭하게 작동합니다. 또한 약간 독점적입니다. Oracle의 DATE 데이터 유형 (두 번째 추적)과 호환되지만 다른 데이터베이스 제품의 DATE / TIME 정밀도로 조정해야합니다.

솔루션 : CLOSED / INCLUSIVE 기본값에 대한 대안의 스펙을 지원하도록 BETWEEN 구문을 수정하여 SQL 언어 스펙을 향상 시키도록 ANSI SQL위원회에 탄원하십시오. 이와 같은 것이 트릭을 수행합니다.

expr1 expr2 사이 [ INCL [USIVE] | EXCL [USIVE]] 및 expr3 [ INCL [USIVE] | 독점 [USIVE]]

이 표현되고 얼마나 쉽게 고려 WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE(또는 WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL)

아마도 ANSI SQL : 2015?


이 답변은 현자 조언입니다.
Basil Bourque

@KevinKirkPatrick-좋은 답변입니다! 또한 의사 결정 문서를 원래의 이유에 대한 객관적인 증거로 찾아보십시오.
Todd

3
나는 개인적 exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3으로 연산자 사이를 유지하여 원거리 술어임을 알 수 있으며 부등식 술어는 반 열린 것을 보장합니다.
Sentinel

@Sentinel, 니스! 나는 나 자신에게 전환을 조기에 선언하지 않을 것이지만 다음 코드 날짜 범위 조건에 대해이 변형을 염두에 두어야합니다. 처음에 홍당무는 exp1> = exp2 AND exp1 <exp3보다 언어 학적 매력이 더 큽니다. 분명히 BETWEEN의 문제를 똑같이 잘 해결합니다. 옵티마이 저가 한 변형에서 다른 변형보다 더 큰 "이해"를 보이는지 관심이 있습니다. 확실히, 당신이 (솔직히 불구하고, 나는 꽤 다르게 처리하는 최적화 실망 할 것) 그런 측면에서뿐만 아니라 더 나은 결과를 얻을 수 있음을 그럴듯하게 보인다
KevinKirkpatrick

@KevinKirkpatrick 나는 차이점이 있는지 확인하기 위해 프로필을 작성 한 적이 없으며, 있다면 실망 할 것입니다.
Sentinel

8

포함 ( a <= x <= b)과 독점 ( a < x < b)은 거의 동일하므로 표준을 만들 때 단순히 하나를 선택해야했습니다. 공통 영어에서 "사이"는 일반적으로 포함되며, SQL 문은 영어 문장과 유사하게 읽히도록되어 있기 때문에 합리적인 선택이 적절했습니다.


4
Half-Open을 생략하면 실제로 영어로 된 사용법이 훨씬 더 혼합됩니다. 우리가 말할 때 "점심은 정오 오후 1시 사이에"우리 평균의 절반 오픈 (13)의 순간에 당신이 수업 시간에 다시 예상되는 / 작품 : 브레이크가 올라가고 00.000 : 00 을 포함하지만 의 첫 순간 1시 시간. a <= x < bHalf-Open입니다.
Basil Bourque

1
@BasilBourque :이 무한한 정확성에 기인 할 수있다 - 예를 들면, 점심 정오 12 사이이다 .... 99.9999999999999 : 59
브랜든

@Brendan 예, 당신은 내 요점을하고 있습니다. 무한 (또는 모호한) 정밀도는 시간 범위를 정의하기 위해 반 개방 방식을 사용하여 처리되는 문제 중 하나입니다. 여기서 중요한 점은 영어 대화에서 우리는 직관적으로 개방형 및 폐쇄 형 (이 답변에 언급 된 것처럼)뿐만 아니라 반 개방형 범위를 많은 생각없이 처리한다는 것입니다. 각 접근법은 목적에 부합합니다. 이것이 BETWEEN의 SQL 정의가 최적이 아닌 이유입니다. 이상적으로 SQL은 KevinKirkpatrick제안을 따릅니다 .
Basil Bourque

2
SQL은 영어와 유사해야하며 포괄적이고 배타적이 동일하지만 분석가와 프로그래머에게는 쿼리 언어입니다. 프로그래머로서 나는 그것이 잘못 정의되었다고 생각하지만 실제로는 중요하지 않습니다. 어쨌든 "BETWEEN"을 사용하지 마십시오. 별거 아니야
Todd

5

연산자는이라고 불리지 않고 이므로 ∩[a,b)라는 BETWEEN의미 는 수학적 술어 "반간 간격"에있는 것보다 영어 구문 "사이에 있음" 의 의미 인 것이 훨씬 더 적합합니다 .


정수 세트에 대한 영어 응용 프로그램뿐만 아니라 모든 응용 프로그램을 고려해야합니다. "1시와 10시 사이", "오후 1시와 오후 1시 사이", "1.0과 5.0 사이"(그램). "5.50에서 10.30 사이"(달러). 연속적인 수량은 논리적으로 (영어로) 배타적 인 것으로 간주됩니다.
Todd

1
문제는 BETWEEN연산자 영어 사이에 "is between"라는 의미를 사용 하지 않는다는 것입니다. 영어에서 "사이"는 사물 을 구분 하는 시간, 공간 또는 간격 입니다 (예 : 배타적 ). 당신이 목표를 걷어차려고하면 공이 득점 사이에 이동해야합니다. 당신이 그들 사이를 통과하지 못한 게시물을 명중하면-당신을 위해 점수가 없습니다.
Disillusioned

1
@CraigYoung은 "1에서 10 사이의 숫자를 선택하십시오"라고 말하면 대부분의 사람들은 1과 10의 숫자를 [가능한 답변 범위에 포함시킬 것입니다. "라고 대답합니다. A의 공간 도메인 당신과 함께 동의하지만 숫자 나는 다른 말하고 싶지만. 에 대한 더 나은 영어 및 사용 여기에 생각보다 더!
AakashM

@AakashM 내 요점은 프로그래밍 의미론을 정당화하기 위해 "사이에"라는 단어의 사전 정의에 의해 단순히 거짓 인 영어에 대한 주장을했다는 것입니다. "1과 10 사이"라는 문구에 대한 일반적인 이해가 있다는 사실은 "사이"의 의미와 관련이 없으며 10 진수 시스템에서 1과 10의 위치와 관련이 있습니다. 인간의 뇌의 "자동 수정"은 "사이에"가 "2에서 9"를 의미하는 것이 우스꽝스러워 보이기 때문에이 경우 엔드 포인트를 배제한다는 것을 무시합니다. "13에서 24 사이"로 동일하게 시도하십시오. 또는 "0과 11 사이".
Disillusioned

당신과 저 사이에서 자연어에 대한 범주 적 주장은 일반적으로 안전하지 않습니다.
AakashM
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.