Время прочтения: 4 мин.
В ходе работы с одной из БД, содержащих данные о транспортных средствах, возникла необходимость выгрузить модели автотранспорта, названия которых начинаются в диапазоне от «А» до «D».
Написав запрос на SQL, с помощью оператора BETWEEN, каково же было моё удивление, когда в результатах выгрузки не оказалось таких марок авто, как DATSUN и DAEWOO, которые точно были в базе данных.
Начав разбираться, я понял следующее — если Вам нужно применить оператор BETWEEN, который выбирает при запросе все значения из заданного диапазона (включая границы), то с датами и числовыми значениями не возникает трудностей, а вот с текстовыми строками всё иначе т.к. значение верхней границы диапазона не будет включено в выборку, если оно не указано точно.
Пример:
Итак, у нас есть таблица “table1” со столбцом “model_car” (тип данных varchar) из которой нам необходимо вывести ее часть, где названия марок автомобилей лежат в диапазоне от А до D.
Таблица table1:
ID | LAST_NAME | FIRST_NAME | MODEL_CAR | YEAR |
1 | Иванов | Петр | Audi | 2010 |
2 | Петров | Иван | BMW | 2015 |
3 | Сидоров | Василий | Dodge | 2017 |
4 | Алексеев | Олег | D | 2019 |
5 | Михайлов | Алексей | Chevrolet | 2012 |
6 | Петрова | Ольга | Jeep | 2015 |
7 | Иванова | Юлия | Volvo | 2016 |
8 | Лужин | Алексей | Mersedes | 2014 |
9 | Абрамов | Александр | Ford | 2017 |
10 | Семенов | Семен | Datsun | 2017 |
Если выполнить следующий запрос:
SELECT *
FROM table1
WHERE model_car BETWEEN ‘A’ AND ‘D’
ORDER BY model_car
То результат его выполнения будет следующим:
ID | LAST_NAME | FIRST_NAME | MODEL_CAR | YEAR |
1 | Иванов | Петр | Audi | 2010 |
2 | Петров | Иван | BMW | 2015 |
5 | Михайлов | Алексей | Chevrolet | 2012 |
4 | Алексеев | Олег | D | 2019 |
Как видно из примера, выведены только значения, начинающиеся с А до С, за исключением строчки, где значение равно D.
Дело в том, что так оператор BETWEEN сравнивает строки неравной длины. Строка “D” короче строки “Dodge” и, при сравнении, дополняется пробелами. Но при сортировке по алфавиту пробелы окажутся опережающими символами и поэтому строка в выборку не попадает.
Выражение “Имя” BETWEEN ‘A’ AND ‘D’ эквивалентно “имя” >= ‘A’ AND “имя” <= ‘D’
То есть, “Audi” и ”Chevrolet” это >= ‘A’ AND <= ‘D’, что удовлетворяет условию, но “Dodge” — это не <= ‘D’. “Dodge” — это > ‘D’.
Чтобы получить все строки, начинающиеся от А до D включительно, то необходимо было в запросе написать так:
model_car BETWEEN ‘A’ AND ‘E’
ID | LAST_NAME | FIRST_NAME | MODEL_CAR | YEAR |
1 | Иванов | Петр | Audi | 2010 |
2 | Петров | Иван | BMW | 2015 |
5 | Михайлов | Алексей | Chevrolet | 2012 |
4 | Алексеев | Олег | D | 2019 |
10 | Семенов | Семен | Datsun | 2017 |
3 | Сидоров | Василий | Dodge | 2017 |
Такой нюанс существует только при работе с символьными данными, поэтому нужно быть внимательным, даже при работе с таким простым оператором, как BETWEEN.
SQL — универсальный язык, поэтому нашу задачу можно было выполнить другими способами:
- через операторы сравнения. Операторы сравнения – это математические символы, которые указывают на определенный тип сравнения между двумя значениями (= равно; > больше; < меньше; >= больше или равно; <= меньше или равно; <> не равно)
SELECT *
FROM table1
WHERE MODEL_CAR <‘E’
- через оператор LIKE. Оператор LIKE используется для того, чтобы находить значение по определённому шаблону. В качестве условия он использует групповые символы, которые могут соответствовать чему-нибудь. Например, знак подчеркивания (_) замещает собой одиночный символ, а знак процента (%) позволяет нам сопоставлять строку любой длины.
SELECT *
FROM table1
WHERE MODEL_CAR LIKE 'A%' or MODEL_CAR LIKE 'B%' or MODEL_CAR LIKE 'C%' or MODEL_CAR LIKE 'D%'
- через функцию SUBSTRING и оператор IN. Функция SUBSTRING извлекает из выражения, которое мы указываем, часть заданной длины начиная от заданной позиции. В нашем случае мы указываем столбец с названиями автомобилей и выделяем только первую букву. Далее через оператора IN определяем набор значений, в который данное значение может быть включено, т.е. указываем перечень автомобилей, которые начинаются с А, В, С, D.
SELECT *,
SUBSTRING (MODEL_CAR,1,1)
FROM table1
where SUBSTRING (MODEL_CAR,1,1) IN ('A', 'B', 'C', 'D')
Какой запрос выбрать, для обработки подобных данных, решать только вам. В свою очередь, искренне надеюсь, что мои советы помогут в решении поставленной задачи.