• Bazy danych
  • Czy SQL BETWEEN obejmuje obie granice? Sprawdź daty i NULL

Czy SQL BETWEEN obejmuje obie granice? Sprawdź daty i NULL

Radosław Stępień • 9 listopada 2026
Porównanie baz danych: widać różnice między tabelami `dev.Dept` i `prod.Dept`, gdzie `sql between` pokazuje, że niektóre rekordy są inne.

Spis treści

Raport z zamówieniami znów pomija część rekordów z ostatniego dnia miesiąca, choć warunek wygląda poprawnie. Operator BETWEEN obejmuje obie granice zakresu, ale przy kolumnie z godziną górna data może oznaczać dopiero początek tego dnia.

BETWEEN obejmuje oba końce, lecz typ kolumny zmienia wynik

  • Granice są domknięte: wartość równa dolnej lub górnej granicy pasuje do zakresu.
  • Daty z godziną: granica zapisana jako data może wykluczyć późniejsze godziny tego samego dnia.
  • Przedział otwarty: dla raportu obejmującego cały dzień końcowy często lepiej użyć warunku „od tej daty włącznie, przed następną”.
  • NULL: rekordy z brakiem wartości nie spełniają warunku zakresu.

Porównanie baz danych: widać różnice między tabelami `dev.Dept` i `prod.Dept`, gdzie `sql between` może pomóc znaleźć dane.

Granice BETWEEN są włączone do zakresu

Wynik leży w przedziale, jeśli jest większy lub równy dolnej granicy i jednocześnie mniejszy lub równy górnej. Tę logikę można zapisać krócej przez BETWEEN:

SELECT order_id, total
FROM orders
WHERE total BETWEEN 100 AND 500;

Zapytanie zwróci zamówienia o wartości od 100 do 500, łącznie z obiema kwotami granicznymi. Tak samo można zapisać warunek jako total >= 100 AND total <= 500. Uważam, że przy prostym zakresie liczbowym BETWEEN jest czytelny, o ile pamiętasz, że końce także przechodzą filtr.

Jeśli granice mają być wykluczone, operator nie pasuje. Zapisz wtedy warunek jawnie, na przykład total > 100 AND total < 500. Różnica jednego znaku może zmienić wynik dla rekordów leżących dokładnie na progu.

Data bez godziny może uciąć rekordy z końca dnia

W tabeli przechowujesz zamówienia jako znaczniki czasu, a raport ma objąć cały marzec. Warunek BETWEEN '2026-03-01' AND '2026-03-31' może wyglądać naturalnie, ale górna granica często odpowiada północy rozpoczynającej 31 marca. Zamówienie zarejestrowane tego dnia po północy wypada wtedy poza zakresem.

Bezpieczniej zdefiniować początek włącznie, a koniec wyłącznie:

WHERE created_at >= '2026-03-01'
  AND created_at <  '2026-04-01'

To podejście obejmuje wszystkie znaczniki czasu w marcu, niezależnie od tego, czy baza przechowuje sekundy, milisekundy czy większą precyzję. Nie trzeba zgadywać ostatniej chwili dnia ani dopisywać ułamków sekundy, które mogą nie pasować do typu kolumny.

Przy kolumnie typu `DATE`, która nie przechowuje godziny, górna granica z BETWEEN działa zgodnie z oczekiwaniem. Problem pojawia się przy `DATETIME` lub typie timestamp, dlatego najpierw sprawdź typ kolumny, a dopiero potem dobierz zapis.

NULL i odwrócone granice wymagają osobnego sprawdzenia

Filtr zakresu nie zamienia braku danych w wartość. Gdy badana kolumna albo jedna z granic ma wartość NULL, warunek nie daje wyniku prawdziwego, więc wiersz nie przechodzi przez WHERE. Jeśli brak wartości ma być uwzględniony, dopisz osobny warunek.

Sytuacja Skutek Co zrobić
Kolumna zawiera NULL Wiersz nie spełnia warunku zakresu. Dodaj OR kolumna IS NULL, jeśli brak wartości ma być częścią wyniku.
Dolna granica jest większa od górnej Zakres nie obejmuje zwykłych wartości. Zweryfikuj kolejność parametrów przed wykonaniem zapytania.
Granice mają różne typy Niektóre silniki odrzucą warunek, inne mogą wykonać konwersję. Użyj zgodnych typów i sprawdź zasady swojego silnika SQL.
Porównywane są wartości zmiennoprzecinkowe Zaokrąglenia reprezentacji mogą dać zaskakujące wyniki blisko granicy. Dla kwot wybierz typ dziesiętny, a dla pomiarów określ akceptowaną tolerancję.

Ostatni przypadek jest podstępny, bo zapytanie może wykonać się bez błędu, a mimo to zachować się inaczej, niż sugeruje zapis liczby. Dokumentacja MySQL opisuje problem przybliżonego przechowywania typów zmiennoprzecinkowych; dla wartości pieniężnych wybór typu danych bywa ważniejszy niż sam operator.

Silnik SQL wpływa na szczegóły, nie na sens operatora

Podstawowa zasada jest wspólna, lecz silniki różnią się w wymaganiach dotyczących typów i w sposobie obsługi wyrażeń. W Transact-SQL dla SQL Server wyrażenie testowane i obie granice muszą mieć zgodne typy danych. Dokumentacja PostgreSQL opisuje zakres jako domknięty, a SQLite zaznacza, że wyrażenie po lewej stronie operatora jest obliczane raz.

W praktyce nie zakładaj, że konwersja tekstu na datę lub liczbę zadziała identycznie w każdym środowisku. Parametry zapytania przekazuj jako wartości właściwego typu, szczególnie gdy aplikacja obsługuje więcej niż jeden silnik bazy.

Najpierw sprawdź typ, potem wybierz granice

Przy debugowaniu rozbieżnego raportu najkrótsza droga prowadzi przez trzy pytania: czy granice są włączone, czy kolumna zawiera czas oraz czy w danych występuje NULL. Gdy zakres dotyczy pełnych dni w kolumnie czasu, zapis z końcem wyłącznym zwykle usuwa problem bez sztucznych końcowych sekund.

Jeśli testujesz sam operator, dodaj do danych rekordy dokładnie na dolnej i górnej granicy oraz jeden tuż poza nimi. Taki mały test ujawnia, czy problem tkwi w logice zakresu, typie kolumny czy parametrach przekazanych przez aplikację.

FAQ - Najczęstsze pytania

Tak. BETWEEN jest operatorem domkniętym, więc działa jak warunek >= dla dolnej granicy oraz <= dla górnej. Przykład total BETWEEN 100 AND 500 obejmuje także wartości 100 i 500.

Przy kolumnie typu DATETIME lub timestamp zapis BETWEEN '2026-03-01' AND '2026-03-31' może traktować górną granicę jako północ rozpoczynającą 31 marca. Późniejsze godziny tego dnia zostaną pominięte. Dla pełnego miesiąca użyj początku włącznie i następnej daty wyłącznie, na przykład created_at >= '2026-03-01' AND created_at < '2026-04-01'.

Wiersz, w którym badana kolumna ma wartość NULL, nie spełnia warunku zakresu i nie przechodzi przez WHERE. Jeśli takie rekordy mają zostać uwzględnione, trzeba dodać osobny warunek, na przykład OR kolumna IS NULL. Podobny problem występuje, gdy jedna z granic ma wartość NULL.

Silniki SQL mogą różnie obsługiwać niezgodne typy granic i konwersje, dlatego wartości należy przekazywać w typach zgodnych z kolumną. Przy liczbach zmiennoprzecinkowych zaokrąglenia mogą zmienić wynik blisko granicy. Dla kwot lepiej użyć typu dziesiętnego, a dla pomiarów określić akceptowaną tolerancję.

Oceń artykuł

Ocena: 5.00 Liczba głosów: 2

Tagi

znaczniki czasu
null
typy danych
liczby zmiennoprzecinkowe
between
Autor Radosław Stępień
Radosław Stępień
Dziedzina programowania i technologii rozwija się w zawrotnym tempie, co sprawia, że ciągłe śledzenie nowinek i głębokie zrozumienie procesów są kluczowe. Nazywam się Radosław Stępień i od 13 lat aktywnie działam w branży IT, dzieląc się swoją wiedzą i doświadczeniem. Moje zainteresowania skupiają się na praktycznych aspektach tworzenia oprogramowania, analizie trendów technologicznych oraz budowaniu satysfakcjonującej ścieżki kariery w tym dynamicznym sektorze. Staram się przedstawiać złożone zagadnienia w sposób przystępny, opierając się na sprawdzonych informacjach i własnych obserwacjach z wieloletniej pracy. Zależy mi na tym, aby treści, które tworzę, były nie tylko merytoryczne i aktualne, ale przede wszystkim pomocne dla każdego, kto chce zgłębić tajniki IT lub rozwijać się zawodowo.

Udostępnij artykuł

Napisz komentarz