SQL BETWEEN to operator używany do określenia zakresu testowanych wartości. Zwracana wartość może być inkluzywna lub mieścić się w zakresie. Lub może być poza zakresem, jeśli dodasz przed nim operator NOT. Działa dla dat, dat z godziną, liczb i ciągów.
Możesz go użyć w klauzulach WHERE w następujących przypadkach:
- WYBIERZ,
- INSERT (z SELECT)
- AKTUALIZACJA,
- i USUŃ.
Działa również dla klauzul HAVING wraz z GROUP BY.
Ale jeśli nie jesteś ostrożny, SQL BETWEEN może doprowadzić Cię do szału, gdy go używasz, zwłaszcza w przypadku dat z czasem.
Ale nie martw się. Mamy przykłady radzenia sobie z problemami w używaniu SQL BETWEEN. Ale wcześniej przykładowe dane, których użyłem, pochodziły z NOAA . Możesz od nich bezpłatnie poprosić o dane pogodowe. Skorzystałem z godzinowych rekordów temperatury dla Stanów Zjednoczonych w roku 2010. Następnie zaimportowałem dane CSV do SQL Server za pomocą SQL Server Management Studio. Zmieniłem nazwy kolumn i dodałem indeks nieklastrowany.
Zacznijmy.
Korzystanie z SQL BETWEEN z datami i godzinami
Musi to być najczęściej wyszukiwana pozycja w przypadku SQL BETWEEN. Użyjemy przykładów, aby wyjaśnić, jak to działa.
Wskazówka 1:w przypadku kolumn DATETIME określ zarówno datę, jak i godzinę
NIEWŁAŚCIWE UŻYCIE
Zacznijmy od niewłaściwego użycia, aby podkreślić ten punkt. Następujące użycie BETWEEN z kolumnami DATETIME da nieoczekiwane wyniki.
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010' AND '01/02/2010'
AND Latitude = 41.995
AND Longitude = -87.9336;
Zapytanie zwraca dane z 2 dni ze stacji pogodowej w pobliżu międzynarodowego lotniska O’Hare w Chicago. Można zauważyć rozpiętość między wartością niższą (01.01.2010) a wartością wyższą (02.01.2010). Oto wynik przedstawiony na rysunku 1.
Rysunek 1 . Zestaw wyników zapytania używającego SQL BETWEEN 2 daty.
Ale gdzie jest problem?
Ma to być rekord godzinowy przez 2 dni. Z tego powodu zestaw wyników powinien zawierać 48 rekordów. Ale zauważ, że to tylko 24. Problem polega na elemencie czasu w DateHour kolumna. Jeśli nie określisz godziny w kolumnie DATETIME, przyjmuje się 00:00 lub 12:00 AM. Pamiętaj też, że dane zaczęły się 1 stycznia 2010 r. o godzinie 01:00, a nie o 12:00.
Tak więc wewnętrznie SQL Server używał DataGodzina POMIĘDZY '01.01.2010 00:00:00.000′ ORAZ ’01/02/2010 00:00:00.000′ . Skąd wiemy?
DATA TO WŁAŚCIWIE ŁAŃCUCH
Zgadza się.
Wartości dat ujęte w pojedyncze cudzysłowy nie są tak naprawdę datami, ale ciągami . SQL Server używa niejawnej konwersji do konwersji ciągu na DATETIME. Po konwersji część czasu zostanie dołączona do daty.
Sprawdźmy za pomocą Uwzględnij rzeczywisty plan wykonania . Naciśnij Ctrl+M w SQL Server Management Studio, a następnie ponownie uruchom poprzedni przykład.
Gdy pojawi się plan wykonania, kliknij prawym przyciskiem myszy Poszukiwanie indeksu operatora i wybierz Właściwości . Zobacz rysunek 2.
Rysunek 2 . Niejawna konwersja ciągu na DATETIME. Jest ukryty w planie wykonania zapytania za pomocą BETWEEN.
Następnie rozwiń Wyszukuj predykaty . Obramowane części rysunku 2 pokazują niejawną konwersję tych 2 ciągów na DATETIME. Ponieważ konwersja niejawna jest wykonywana wewnętrznie , nowicjusze są zdezorientowani, dlaczego ich oczekiwania w zestawie wyników nie są spełnione.
PRAWIDŁOWE UŻYCIE
Poniższy przykład zwróci rekordy godzinowe między 8:00 a 12:00 2 stycznia 2010 r.
SELECT * FROM TemperatureData
WHERE DateHour BETWEEN '01/02/2010 08:00' AND '01/02/2010 12:00'
AND Latitude = 41.995
AND Longitude = -87.9336;
Musisz określić część czasu, zwłaszcza gdy daty są takie same. W przeciwnym razie oczekiwane rezultaty się nie spełnią.
Aby zwrócić rekordy z całego dnia, to nie zadziała:
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour = '06/01/2010'
AND Latitude = 41.995
AND Longitude = -87.9336;
Zwróci tylko 1 rekord – ten z 1 czerwca 2010 o godzinie 12:00. Ale używając BETWEEN z określonymi czasami, możesz zwrócić rekord każdej godziny dla całego dnia. Zobacz następny przykład.
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010 00:00' AND '06/01/2010 23:00'
AND Latitude = 41.995
AND Longitude = -87.9336;
Zauważ, że określiłem tylko do 23:00. Jeśli Twoje dane są używane o dowolnej porze dnia, wybierz 23:59 lub 23:59 jako wyższą wartość zakresu. Określ sekundy również, jeśli tego potrzebujesz.
Wskazówka 2:Rozważ typ danych DATE
Jeśli nie potrzebujesz części czasu, zamiast tego rozważ typ danych DATE. I unikniesz kłopotów wspomnianych powyżej.
SQL BETWEEN z liczbami
Przejdźmy do liczb.
Wskazówka 3:Uwzględnij część dziesiętną dla wartości niecałkowitych
SELECT
DateHour
,[Hourly_Heating_Degree_Hours]
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010' AND '06/5/2010 23:00'
AND [Hourly_Heating_Degree_Hours] BETWEEN 5.0 AND 7.0
AND Latitude = 41.995
AND Longitude = -87.9336;
Zwróć uwagę na dodanie kolejnego warunku dotyczącego liczb. Wyniki będą dalej ograniczone do 5 i 7 stopni.
Używając typów danych DECIMAL, MONEY lub FLOAT, określ część dziesiętną, nawet jeśli jest równa zero, na przykład 52,00 lub 10,0000. W ten sposób unikniesz niejawnej konwersji do docelowych typów danych DECIMAL, MONEY lub FLOAT.
SQL BETWEEN z ciągami
Wskazówka 4:W przypadku ciągów zakres jest oparty na sortowaniu
W przypadku ciągów BETWEEN ocenia wartości w kolejności alfabetycznej. „A” jest najmniejsze, a „Z” największe. Można też powiedzieć, że generalnie ocena opiera się na zestawieniu. Ponieważ angielski nie jest jedynym językiem obsługiwanym przez SQL Server. Składanie zapewnia zasady sortowania, wielkość liter i czułość na akcent. Skorzystajmy z AdventureWorks baza danych dla tego przykładu. Sprawdź poniższy kod i wynik na rysunku 3.
USE AdventureWorks
GO
SELECT
LastName
,FirstName
,MiddleName
FROM Person.Person
WHERE Lastname BETWEEN 'Spanaway' AND 'Splane'
ORDER BY LastName;
Rysunek 3 . Zestaw wyników zapytania przy użyciu BETWEEN z ciągami.
Zakres obejmuje nazwisko Spanaway . Ale gdzie jest Splane ? Nie ma go w bazie danych. Tak więc wynik osiągnął tylko Spicer .
Wskazówki dotyczące SQL BETWEEN dla wszystkich obsługiwanych typów danych
Niezależnie od tego, czy używasz BETWEEN dla dat, liczb czy ciągów znaków, istnieją wspólne rzeczy, o których powinieneś wiedzieć. To może być zdrowy rozsądek, ale nadal dzieje się to przez pomyłkę. Przeczytaj, jak to się może stać.
Wskazówka nr 5:zarówno wartości początkowe, jak i końcowe nie mogą być NULL
BETWEEN potrzebuje wartości początkowej i końcowej dla zakresu. Każdy powinien mieć wartość inną niż NULL. Poniżej znajduje się przykład z wartością końcową NULL.
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010' AND NULL;
Może się tak zdarzyć, jeśli wywołasz instrukcję SELECT z aplikacji lub procedury składowanej, a nie sprawdziłeś jej prawidłowo.
Wskazówka nr 6:wartość początkowa nie może być większa niż wartość końcowa
Nic nie zostanie również zwrócone, jeśli obie wartości nie są NULL, ale zakres jest odwrócony. Oto przykład.
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/30/2010' AND '01/01/2010';
Oprócz dat poniższe wyrażenia również nie zwrócą wyniku:
- wartość POMIĘDZY 100 A -200. Ponieważ -200 jest mniejsze niż 100.
- pracuj MIĘDZY „Opiekunem zoo” A „Księgowym”. Ponieważ „Z” jest większe niż „A”.
Wskazówka nr 7:wartości zakresu powinny być tymi samymi typami danych
Czasami kontrolki interfejsu użytkownika mają nieoczekiwane dane wyjściowe. Albo po prostu wybraliśmy niewłaściwą nieruchomość. A jeśli nie sprawdzimy tego przed przekazaniem go do SQL Server, może się zdarzyć taka sytuacja:
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010' AND 'Saturday, June 5, 2010'
AND Latitude = 41.995
AND Longitude = -87.9336;
Wystąpi błąd konwersji z ciągu znaków na datę.
Tak więc lekcja od wskazówek od 5 do 7 polega na sprawdzeniu wartości początkowej i końcowej zakresu .
Wskazówka nr 8:nie używaj BETWEEN, aby wykluczyć wartości
Rozważ inny przykład.
SELECT
MONTH(DateHour) AS [Month]
,round(AVG([Hourly_Heating_Degree_Hours]),2) AS AverageTemperature
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010 00:00' AND '06/30/2010 23:00'
AND DateHour NOT BETWEEN '05/01/2010 00:00' AND '05/31/2010 23:00'
AND Latitude = 41.995
AND Longitude = -87.9336
GROUP BY MONTH(DateHour);
Spowoduje to zwrócenie średniej miesięcznej od stycznia do czerwca, ale wykluczy maj. Wykluczenie rekordów za maj 2010 jest możliwe dzięki NOT BETWEEN. Oto wynik przedstawiony na rysunku 4.
Rysunek 4 . Zestaw wyników zapytania przy użyciu NOT BETWEEN.
SQL BETWEEN w porównaniu z innymi operatorami
Wskazówka nr 9:Użyj IN, jeśli potrzebujesz listy, a nie zakresu
Operator IN określa, czy wartość pasuje do dowolnej wartości z listy lub podzapytania. W międzyczasie użycie NOT IN sprawdza, czy wartość się nie zgadza.
Operatory BETWEEN i IN filtrują dane na podstawie wielu wartości. Różnica polega jednak na zestawie dopasowanych wartości. BETWEEN używa zakresu. Ale IN używa wartości oddzielonych przecinkami na liście lub wierszach w podzapytaniu.
Sprawdź poniższy przykład.
SELECT
DateHour
,[Hourly_Heating_Degree_Hours]
FROM TemperatureData
WHERE DateHour BETWEEN '06/01/2010' AND '06/5/2010 23:00'
AND [Hourly_Heating_Degree_Hours] IN (5.2, 6, 7, 3.7)
AND Latitude = 41.995
AND Longitude = -87.9336;
Spójrz na listę wartości używanych przez IN. Nie musi to być lista rosnących wartości. Ostatnia wartość na liście (3.7) jest również najmniejszą z liczb.
Wskazówka nr 10:wybierz BETWEEN lub>=za pomocą <=
W czasie wykonywania SQL Server konwertuje BETWEEN do>=z operatorami <=. Skąd wiemy?
Spójrz na poniższy kod.
SELECT
DateHour
,AVG(Hourly_Heating_Degree_Hours) AS AverageTemp
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010 08:00' AND '01/01/2010 12:00'
GROUP BY DateHour;
SELECT
DateHour
,AVG(Hourly_Heating_Degree_Hours) AS AverageTemp
FROM TemperatureData
WHERE DateHour >= '01/01/2010 08:00'
AND DateHour <= '01/01/2010 12:00'
GROUP BY DateHour;
Oba zapytania będą miały taki sam zestaw wyników, jak ten na rysunku 5.
Rysunek 5 . Wynik ustawiony za pomocą BETWEEN lub>=z <=.
Mają też taki sam plan wykonania, jak widać na rysunku 6.
Rysunek 6 . Plan wykonania 2 zapytań porównujących użycie operatorów BETWEEN oraz>=i <=.
Ale o to chodzi.
Zwróć uwagę na pierwszy indeks Szukaj operator na rysunku 6. Następnie zobacz Szukaj predykatów . Czy widzisz słowo kluczowe BETWEEN? Nie ma, prawda? Ponieważ jest konwertowany na>=z operatorami <=. To są operatory obecne w Predykatach wyszukiwania .
Ale to nie wszystko.
Jeśli najedziesz myszą na drugi szukanie indeksu operatora, zobaczysz te same właściwości, co pierwsze szukanie indeksu .
Wygląda więc na to, że operator BETWEEN jest skrótem do>=z <=operatorami . Napiszesz więcej, jeśli użyjesz tego drugiego. Zobaczysz tę samą konwersję, gdy BETWEEN zostanie użyte w liczbach i ciągach.
Ostatecznie to od Ciebie zależy, czy użyjesz operatorów BETWEEN czy>=i <=. Czas konwersji potrzebny do konwersji BETWEEN jest znikomy. Ale jeśli nadal nie chcesz tego dodatkowego, nieistotnego czasu, użyj operatorów>=i <=.
Podsumowanie
SQL BETWEEN jest dobry do pobierania danych zawierających zakres. I nie jest to takie trudne w użyciu. Nawet wartości DATETIME można zarządzać za pomocą BETWEEN. Tylko upewnij się, że odpowiednio pokryłeś część czasu. Jest to również równoważne użyciu>=z <=. To od Ciebie zależy, którego wolisz używać.
Możesz dodać tę stronę do zakładek, aby uzyskać wskazówki dotyczące SQL BETWEEN dotyczące dat, liczb i ciągów, gdy ich potrzebujesz.
Jeśli masz jakieś sztuczki BETWEEN, których nie omówiliśmy, możesz podzielić się nimi z nami w sekcji Komentarze. A jeśli podoba Ci się ten artykuł, udostępnij go, naciskając przyciski mediów społecznościowych.
Życzę wszystkim miłego kodowania!