Database
 sql >> Baza danych >  >> RDS >> Database

SQL BETWEEN — inteligentne wskazówki dotyczące skanowania w poszukiwaniu zakresu wartości

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!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dostarczanie prezentów świątecznych:model danych Świętego Mikołaja

  2. Wszystko, co musisz wiedzieć o standardach kodowania zapytań SQL

  3. Podziel duże operacje usuwania na porcje

  4. Zindeksowane widoki i statystyki

  5. Ściągawka SQL UNION z 10 łatwymi i przydatnymi wskazówkami