SQL BETWEEN е оператор, използван за определяне на диапазон от стойности за тестване. Върнатата стойност може да бъде включваща или в рамките на диапазона. Или може да е извън диапазона, ако добавите оператора NOT преди него. Работи за дати, дати с час, числа и низове.
Можете да го използвате в клаузи WHERE за следното:
- ИЗБЕРЕТЕ,
- INSERT (с SELECT)
- АКТУАЛИЗИРАНЕ,
- и ИЗТРИВАНЕ.
Работи и за клаузи HAVING заедно с GROUP BY.
Но ако не внимавате, SQL BETWEEN може да ви побърка, когато го използвате, особено с дати с времето.
Не се притеснявай обаче. Имаме примери за справяне с проблемите при използването на SQL МЕЖДУ. Но преди това примерните данни, които използвах, идват от NOAA . Можете да поискате данни за времето безплатно от тях. Използвах почасовите температурни записи за Съединените щати през 2010 г. След това импортирах CSV данните в SQL Server с помощта на SQL Server Management Studio. Преименувах колоните и добавих неклъстериран индекс.
Да започнем.
Използване на SQL МЕЖДУ с дати и часове
Това трябва да е най-търсеният елемент, когато работите със SQL МЕЖДУ. Ще използваме примери, за да обясним как работи.
Съвет №1:За колони DATETIME посочете както датата, така и часа
ГРЕШНО УПОТРЕБА
Нека започнем с грешната употреба, за да подчертаем тази точка. Следното използване на BETWEEN с колони DATETIME ще даде неочаквани резултати.
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;
Заявката връща данни за 2 дни от метеорологична станция близо до международното летище O’Hare в Чикаго. Можете да забележите диапазона между по-ниска стойност (01/01/2010) и по-висока стойност (01/02/2010). Ето набора от резултати на фигура 1.
Фигура 1 . Набор от резултати от заявка, използваща SQL МЕЖДУ 2 дати.
Но къде е проблемът?
Предполага се, че това е почасов рекорд за 2 дни. Поради това наборът от резултати трябва да има 48 записа. Но имайте предвид, че е само 24. Проблемът е в елемента време на DateHour колона. Когато не посочите часа в колона DATETIME, той приема 00:00 или 12:00 сутринта. Също така имайте предвид, че данните започват на 1 януари 2010 г. в 01:00 ч. сутринта, а не в 12:00 ч.
И така, вътрешно SQL Server използва DateHour МЕЖДУ 01/01/2010 00:00:00,000′ И 01/02/2010 00:00:00,000′ . Откъде знаем?
ДАТАТА ВЪЩНОСТ Е НИЗ
Точно така.
Стойностите за дати, затворени в единични кавички, всъщност не са дати, а низове . SQL Server използва имплицитно преобразуване, за да преобразува низа в DATETIME. След преобразуването, частта от времето ще бъде добавена към датата.
Нека да проверим с Включи действителен план за изпълнение . Натиснете Ctrl-M в SQL Server Management Studio, след което стартирайте отново предишния пример.
Когато се появи планът за изпълнение, щракнете с десния бутон върху Търсене в индекс оператор и изберете Свойства . Вижте Фигура 2.
Фигура 2 . Неявно преобразуване на низ в DATETIME. Той е скрит в плана за изпълнение на заявка, използваща BETWEEN.
След това разгънете Търсене на предикати . Частите в полето на фигура 2 показват имплицитното преобразуване на 2 низа в DATETIME. Тъй като неявното преобразуване се извършва вътрешно , начинаещите се объркват защо очакванията им в набора от резултати не са изпълнени.
ПРАВИЛНА УПОТРЕБА
Примерът по-долу ще върне почасовите записи между 8:00 и 12:00 ч. на 2 януари 2010 г.
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;
Трябва да посочите частта от времето, особено когато датите са еднакви. Или очакваните ви резултати няма да се случат.
За да върнете записите за целия ден, това няма да работи:
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour = '06/01/2010'
AND Latitude = 41.995
AND Longitude = -87.9336;
Ще върне само 1 запис – този за 1 юни 2010 г. в 12:00 ч. Но като използвате BETWEEN с посочените часове, можете да върнете записа за всеки час за целия ден. Вижте следващия пример.
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;
Имайте предвид, че посочих само до 23:00 часа. Ако данните ви се използват по всяко време на деня, използвайте 23:59 или 23:59 ч. в по-високата стойност на диапазона. Посочете и секундите, ако имате нужда от това.
Съвет №2:Помислете за типа данни DATE
Ако не се нуждаете от времевата част, помислете за типа данни DATE. И ще избегнете проблемите, споменати по-горе.
SQL МЕЖДУ с числа
Да преминем към числата.
Съвет №3:Включете десетичната част за нецелочислени стойности
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;
Обърнете внимание на добавянето на друго условие, включващо числа. Освен това резултатите ще бъдат ограничени до 5 и 7 градуса.
Когато използвате типове данни DECIMAL, MONEY или FLOAT, посочете десетичната част, дори ако е нула, като 52,00 или 10,0000. По този начин избягвате неявно преобразуване към целевите типове данни DECIMAL, MONEY или FLOAT.
SQL МЕЖДУ с низове
Съвет №4:За низове обхватът се основава на съпоставяне
При низове BETWEEN оценява стойности въз основа на азбучен ред. „А“ е най-малкото, а „Z“ е най-голямото. Можете също да кажете, че като цяло оценката се основава на съпоставяне. Тъй като английският не е единственият език, който SQL Server поддържа. Колекция предоставя правила за сортиране, чувствителност към малки и големи букви и ударение. Нека използваме AdventureWorks база данни за този пример. Вижте кода по-долу и резултата на фигура 3.
USE AdventureWorks
GO
SELECT
LastName
,FirstName
,MiddleName
FROM Person.Person
WHERE Lastname BETWEEN 'Spanaway' AND 'Splane'
ORDER BY LastName;
Фигура 3 . Набор от резултати от заявка, използваща BETWEEN с низове.
Диапазонът обхваща фамилното име Spanaway . Но къде е Splane ? Не съществува в базата данни. Така че резултатът достигна само до Spicer .
SQL МЕЖДУ Съвети за всички поддържани типове данни
Независимо дали използвате BETWEEN за дати, числа или низове, има често срещани неща, които трябва да знаете. Това може да е здрав разум, но все пак се случва по погрешка. Прочетете как може да се случи това.
Съвет №5:И началната и крайната стойност не могат да бъдат NULL
BETWEEN се нуждае от начални и крайни стойности за диапазона. Всеки трябва да има стойност, която не е NULL. По-долу има пример с крайна стойност NULL.
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/01/2010' AND NULL;
Това може да се случи, ако извикате израза SELECT от приложение или съхранена процедура и не сте го потвърдили правилно.
Съвет №6:Началната стойност не може да бъде по-голяма от крайната
Нищо също няма да бъде върнато, ако и двете стойности не са NULL, но диапазонът е обърнат. Ето един пример.
SELECT
DateHour
,Hourly_Heating_Degree_Hours
FROM TemperatureData
WHERE DateHour BETWEEN '01/30/2010' AND '01/01/2010';
Освен датите, следните изрази също няма да върнат резултат:
- стойност МЕЖДУ 100 И -200. Защото -200 е по-ниско от 100.
- работа МЕЖДУ „Пазител на зоопарка“ И „Счетоводител“. Защото „Z“ е по-голямо от „A“.
Съвет №7:Стойностите на диапазона трябва да са едни и същи типове данни
Понякога контролите на потребителския интерфейс имат неочакван изход. Или просто сме взели грешен имот. И ако не го проверим, преди да го предадем на SQL Server, може да се случи ситуация като тази:
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;
Ще възникне грешка при преобразуване от символен низ към дата.
И така, урокът от Съвет #5 до #7 е да проверите началните и крайните стойности на диапазона .
Съвет №8:Използвайте NOT BETWEEN, за да изключите стойности
Помислете за друг пример.
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);
Това ще върне средната месечна стойност от януари до юни, но ще изключи май. Изключването на записите за май 2010 г. става възможно от НЕ МЕЖДУ. Ето набора от резултати на фигура 4.
Фигура 4 . Набор от резултати от заявка, използваща NOT BETWEEN.
SQL МЕЖДУ В сравнение с други оператори
Съвет №9:Използвайте IN, ако имате нужда от списък, а не от диапазон
Операторът IN определя дали дадена стойност съответства на която и да е стойност в списък или подзаявка. Междувременно използването на NOT IN проверява дали дадена стойност не съвпада.
Операторите BETWEEN и IN филтрират данни въз основа на множество стойности. Но разликата се състои в съпоставянето на набора от стойности. BETWEEN използва диапазон. Но IN използва разделени със запетая стойности в списък или редове в подзаявка.
Вижте примера по-долу.
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;
Вижте списъка със стойности, използвани от IN. Не е необходимо да е списък с нарастващи стойности. Последната стойност в списъка (3.7) също е най-малката сред числата.
Съвет №10:Изберете от МЕЖДУ или>=с <=
По време на изпълнение SQL Server преобразува BETWEEN в>=с оператори <=. Откъде знаем?
Вижте кода по-долу.
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;
И двете заявки ще имат същия набор от резултати като този на фигура 5.
Фигура 5 . Резултат се задава при използване на BETWEEN или>=с <=.
Те също имат същия план за изпълнение, както се вижда на фигура 6.
Фигура 6 . План за изпълнение на 2 заявки, сравняващи използването на операторите BETWEEN и>=и <=.
Но ето какво е.
Обърнете внимание на първия Индекс Търсене оператор на фигура 6. След това вижте Търсене на предикати . Виждате ли ключовата дума BETWEEN? Няма такъв, нали? Тъй като се преобразува в>=с <=оператори. Това са операторите, присъстващи в Търсене на предикати .
Но има още.
Ако задържите курсора на мишката си до второто търсене в индекс оператор, ще видите същите свойства като първия Index Seek .
Така че изглежда, че операторът BETWEEN е пряк път към>=с <=оператори . Ще пишете повече, ако използвате последното. Ще видите същото преобразуване, когато се използва BETWEEN в числа и низове.
В крайна сметка от вас зависи дали използвате операторите BETWEEN или>=и <=. Времето за преобразуване, необходимо за преобразуване МЕЖДУ, е незначително. Но ако все пак не искате това допълнително, незначително време, използвайте операторите>=и <=.
Долен ред
SQL BETWEEN е добър за извличане на данни, включително за диапазона. И не е толкова трудно да се използва. Дори стойностите DATETIME се управляват с BETWEEN. Просто се уверете, че покривате правилно частта от време. Също така е еквивалентно на използване на>=с <=. От вас зависи кое предпочитате да използвате.
Можете да маркирате тази страница, за да получите съвети за SQL МЕЖДУ дати, числа и низове, когато имате нужда от тях.
Ако имате някои трикове с помощта на BETWEEN, които не сме обхванали, можете да ги споделите с нас в секцията за коментари. И ако ви харесва тази статия, моля, споделете я, като натиснете бутоните на социалните медии.
Приятно кодиране на всички!