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ę:
wyr1 MIĘDZY wyraż2 [ WŁĄCZNIE [USIVE] | WYŁĄCZENIEM [USIVE]] I wyrażenie3 [ WŁĄCZNIE [USIVE] | EKSKLUZYWNY] ]
Zastanów się, jak łatwo jest wyrazić WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE
(lub po prostu WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL
)
Może ANSI SQL: 2015?