Półotwarte (lub pół-Open, przymknięte , Half-Bounded ) interwały ( [a,b)
, gdzie x
należy do przedziału MFF a <= x < b
) są dość powszechne na programowaniu, ponieważ mają one wiele dogodnych właściwości.
Czy ktoś może przedstawić uzasadnienie wyjaśniające, dlaczego SQL BETWEEN
używa zamkniętego przedziału ( [a,b]
)? To jest esp. niewygodne dla dat. Dlaczego miałbyś BETWEEN
się tak zachowywać?
Odpowiedzi:
Myślę, że włączenie
BETWEEN
jest bardziej intuicyjne (i najwyraźniej tak samo zrobili projektanci SQL) niż półotwarty przedział. Na przykład, jeśli powiem „Wybierz liczbę od 1 do 10”, większość osób będzie zawierać liczby 1 i 10. Interwał otwarty jest w rzeczywistości szczególnie mylący dla nie-programistów, ponieważ jest asymetryczny. Niekiedy programiści używają języka SQL do tworzenia prostych zapytań, a semantyczna półotwarta byłaby dla nich znacznie bardziej zagmatwana.źródło
PYTANIE: Dlaczego SQL zawiera MIĘDZY włącznie?
ODPOWIEDŹ: Ponieważ projektanci języka SQL podjęli kiepską decyzję projektową, ponieważ nie dostarczyli składni, która pozwoliłaby programistom określić, który z 4 wariantów BETWEEN (zamknięty, pół-otwarty-lewy, pół-otwarty-prawy lub otwarty ) woleliby.
ZALECENIE: O ile / dopóki nie zostanie zmieniony standard SQL, nie używaj MIĘDZY datami / godzinami. Zamiast tego nabądź zwyczaju kodowania porównań zakresu DATE jako niezależnych warunków na granicach początkowych i końcowych zakresu BETWEEN. Jest to trochę zbyt szczegółowe, ale pozostawi Ci warunki do pisania, które są intuicyjne (a więc mniej prawdopodobne, że będą wadliwe) i jasne dla optymalizatorów bazy danych, umożliwiając określenie optymalnych planów wykonania i użycie indeksów.
Na przykład, jeśli zapytanie akceptuje specyfikację dnia wejściowego i powinno zwrócić wszystkie rekordy, które przypadły w tym dniu, kodujesz jako:
WHERE DATE_FIELD >= :dt AND DATE_FIELD < :dt+1
Próba napisania logiki przy użyciu BETWEEN ryzykuje problemy z wydajnością i / lub błędny kod. Trzy typowe błędy:
1)
WHERE DATE_FIELD BETWEEN :dt AND :dt+1
To prawie na pewno błąd - użytkownik oczekuje, że zobaczy tylko rekordy dla określonej daty, ale pewnego dnia zakończy się raport zawierający rekordy od godziny 12:00 następnego dnia.
2)
WHERE TRUNC(DATE_FIELD) = :dt
Daje prawidłową odpowiedź, ale zastosowanie funkcji do DATE_FIELD sprawi, że większość indeksowania / statystyk stanie się bezużyteczna (chociaż czasami DBA próbują pomóc, dodając indeksy oparte na funkcjach do pól daty - nadal spalając roboczogodziny i miejsce na dysku oraz dodając koszty ogólne do IUD operacje na stole)
3)
WHERE EVENT_DATE BETWEEN :dt AND :dt + 1-1/24/60/60
Tom Kyte, nadzwyczajny guru Oracle, zaleca to mniej niż eleganckie (IMO) rozwiązanie. Działa świetnie, dopóki nie spędzasz całego dnia na znalezieniu „1-1 / 24/06/60” w zapytaniu, które daje niekompletne wyniki ... lub dopóki przypadkowo nie użyjesz go w polu TIMESTAMP. Ponadto jest to trochę zastrzeżone; zgodny z typem danych DATE Oracle (który śledzi do drugiego), ale należy go dostosować do dokładności DATA / CZAS różnych produktów bazodanowych.
ROZWIĄZANIE: Złóż petycję do komitetu ANSI SQL w celu ulepszenia specyfikacji języka SQL poprzez modyfikację składni BETWEEN w celu obsługi specyfikacji alternatyw dla wartości domyślnej CLOSED / INCLUSIVE. Coś takiego mogłoby załatwić sprawę:
Zastanów się, jak łatwo jest wyrazić
WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE
(lub po prostuWHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL
)Może ANSI SQL: 2015?
źródło
exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3
to, jak możesz zachować operatora między, więc wiesz, że jest to predykat dystansowy, a predykat nierówności zapewnia, że jest częściowo otwarty.Zarówno inclusive (
a <= x <= b
), jak i exclusive (a < x < b
) są mniej więcej tak samo powszechne, więc przy tworzeniu standardów po prostu musiał wybrać jeden. „Pomiędzy” we wspólnym języku angielskim jest zwykle włącznie, a wyrażenie SQL ma brzmieć podobnie do zdania w języku angielskim, więc włączenie było rozsądnym wyborem.źródło
a <= x < b
jest półotwarty.Operator nie jest wywoływany
∩[a,b)
, jest wywoływanyBETWEEN
, więc znacznie bardziej odpowiednie jest, aby jego semantyka była w angielskiej frazie „jest pomiędzy” niż w predykacie matematycznym „jest w półotwartym przedziale”.źródło
BETWEEN
operator nie używa semantyki angielskiej frazy „jest pomiędzy”. W języku angielskim „pomiędzy” to czas, przestrzeń lub interwał, który oddziela rzeczy (tj. Jest wyłączny ). Jeśli spróbujesz kopnąć gola, piłka musi przejść między słupkami, aby zdobyć bramkę. Jeśli trafisz w słupek, nie przechodząc między nimi - nie uzyskasz żadnego wyniku.