alan_beaulieu-learning_sql-ru (865932), страница 15
Текст из файла (страница 15)
Вот чтопроисходит, если задать первой верхнюю границу:mysql> SELECT emp_id, fname, lname, start_date> FROM employee> WHERE start_date BETWEEN '20030101' AND '20010101';Empty set (0.00 sec)Как видите, не возвращено никаких данных. Это объясняется тем, чтофактически из одного заданного условия сервер генерирует два, используя операторы <= и >=:mysql> SELECT emp_id, fname, lname, start_date> FROM employee> WHERE start_date >= '20030101'> AND start_date <= '20010101';Empty set (0.00 sec)Поскольку такая дата – одновременно позднее 1 января 2003 года ираньше 1 января 2001 года – не существует, по запросу возвращаетсяпустой набор.
Далее следует отметить второй подводный камень прииспользовании оператора between: необходимо помнить, что верхняяи нижняя границы включаются в диапазон. В данном случае я хотел,чтобы нижней границей была дата 20010101, а верхней – 20021231,а не 20030101. Даже несмотря на то, что, скорее всего, никто из сотрудников банка не начал работать в первый же день Нового 2003 года, лучше задавать именно то, что требуется.Как и для дат, можно создавать условия, определяющие диапазон длячисел.
Числовые диапазоны довольно просты для понимания, как видно из следующего примера:mysql> SELECT account_id, product_cd, cust_id, avail_balance> FROM account> WHERE avail_balance BETWEEN 3000 AND 5000;+++++| account_id | product_cd | cust_id | avail_balance |+++++80Глава 4. Фильтрация|3 | CD|1 |3000.00 ||14 | CD|7 |5000.00 ||15 | CHK|8 |3487.19 |+++++3 rows in set (0.03 sec)Выбираются все счета, доступный остаток которых составляет от 3000до 5000 долларов. Еще раз подчеркну, что первой задается нижняяграница.Строковые диапазоныДиапазоны дат и чисел легко представить, но можно также создаватьусловия для поиска диапазона строк, проиллюстрировать которыечуть сложнее.
Например, требуется найти клиентов, для которых в определенный диапазон попадает номер социальной страховки. Форматномера социальной страховки – 'XXXXXXXXX', где X – число от 0 до 9.Требуется найти всех клиентов, номер социальной страховки которыхнаходится между '500000000' и '999999999'. Вот как может выглядеть такое выражение:mysql> SELECT cust_id, fed_id> FROM customer> WHERE cust_type_cd = 'I'> AND fed_id BETWEEN '500000000' AND '999999999';+++| cust_id | fed_id|+++|5 | 555555555 ||6 | 666666666 ||7 | 777777777 ||8 | 888888888 ||9 | 999999999 |+++5 rows in set (0.01 sec)Для работы со строковыми диапазонами необходимо знать порядоксимволов в наборе символов (порядок, в котором сортируются символы в наборе символов, называется сопоставлением (collation)).Условия членстваВ некоторых случаях выражение ограничивается не одним значениемили диапазоном значений, а конечным набором (set) значений.
Например, требуется выбрать все счета, кодом типа которых является 'CHK','SAV', 'CD' или 'MM':mysql> SELECT account_id, product_cd, cust_id, avail_balance> FROM account> WHERE product_cd = 'CHK' OR product_cd = 'SAV'> OR product_cd = 'CD' OR product_cd = 'MM';Типы условий81+++++| account_id | product_cd | cust_id | avail_balance |+++++|1 | CHK|1 |1057.75 ||2 | SAV|1 |500.00 ||3 | CD|1 |3000.00 ||4 | CHK|2 |2258.02 ||5 | SAV|2 |200.00 ||6 | CHK|3 |1057.75 ||7 | MM|3 |2212.50 ||8 | CHK|4 |534.12 ||9 | SAV|4 |767.77 ||10 | MM|4 |5487.09 ||11 | CHK|5 |2237.97 ||12 | CHK|6 |122.37 ||13 | CD|6 |10000.00 ||14 | CD|7 |5000.00 ||15 | CHK|8 |3487.19 ||16 | SAV|8 |387.99 ||17 | CHK|9 |125.67 ||18 | MM|9 |9345.55 ||19 | CD|9 |1500.00 ||20 | CHK|10 |23575.12 ||23 | CHK|12 |38552.05 |+++++21 rows in set (0.02 sec)На создание этого блока where (всего четыре условия, разделенных операторами or) ушло не слишком много сил и времени.
А представьте, если бы набор выражений содержал 10 или 20 элементов? В таких ситуациях можно использовать оператор in:SELECT account_id, product_cd, cust_id, avail_balanceFROM accountWHERE product_cd IN ('CHK','SAV','CD','MM');При использовании оператора in записывается единственное условие,сколько бы у вас ни было выражений.ПодзапросыМожно самостоятельно создать набор выражений, например ('CHK','SAV','CD','MM'), но сделать это можно и с помощью подзапроса. Например, у всех четырех типов счетов, используемых в предыдущем запросе, столбец product_type_cd имеет значение 'ACCOUNT'.
В следующейверсии запроса для извлечения четырех кодов типов счетов вместо явного указания их имен используется подзапрос к таблице product:mysql> SELECT account_id, product_cd, cust_id, avail_balance> FROM account> WHERE product_cd IN (SELECT product_cd FROM product>WHERE product_type_cd = 'ACCOUNT');82Глава 4. Фильтрация+++++| account_id | product_cd | cust_id | avail_balance |+++++|1 | CHK|1 |1057.75 ||2 | SAV|1 |500.00 ||3 | CD|1 |3000.00 ||4 | CHK|2 |2258.02 ||5 | SAV|2 |200.00 ||6 | CHK|3 |1057.75 ||7 | MM|3 |2212.50 ||8 | CHK|4 |534.12 ||9 | SAV|4 |767.77 ||10 | MM|4 |5487.09 ||11 | CHK|5 |2237.97 ||12 | CHK|6 |122.37 ||13 | CD|6 |10000.00 ||14 | CD|7 |5000.00 ||15 | CHK|8 |3487.19 ||16 | SAV|8 |387.99 ||17 | CHK|9 |125.67 ||18 | MM|9 |9345.55 ||19 | CD|9 |1500.00 ||20 | CHK|10 |23575.12 ||23 | CHK|12 |38552.05 |+++++21 rows in set (0.03 sec)Подзапрос возвращает набор из четырех значений, а основной запроспроверяет, соответствует ли значение столбца product_cd значениям,возвращенным подзапросом.Оператор not inИногда требуется проверить, присутствует ли определенное выражение в наборе выражений, а иногда нужно удостовериться в его отсутствии.
В таких ситуациях можно использовать оператор not in (нет в):mysql> SELECT account_id, product_cd, cust_id, avail_balance> FROM account> WHERE product_cd NOT IN ('CHK','SAV','CD','MM');+++++| account_id | product_cd | cust_id | avail_balance |+++++|21 | BUS|10 |0.00 ||22 | BUS|11 |9345.55 ||24 | SBL|13 |50000.00 |+++++3 rows in set (0.02 sec)Этот запрос находит все счета, не являющиеся текущими, депозитными, депозитными сертификатами или депозитными счетами денежного рынка.83Типы условийУсловия соответствияДо сих пор были рассмотрены условия, выделяющие определеннуюстроку, диапазон строк или набор строк. Еще один тип условий касается частичного соответствия строк. Например, требуется найти всех сотрудников, фамилия которых начинается с «T».
Получить первую букву значения столбца lname можно с помощью встроенной функции:mysql> SELECT emp_id, fname, lname> FROM employee> WHERE LEFT(lname, 1) = 'T';++++| emp_id | fname | lname |++++|3 | Robert | Tyler ||7 | Chris | Tucker ||18 | Rick | Tulman |++++3 rows in set (0.01 sec)Хотя встроенная функция left() выполняет то, что требуется, она необеспечивает особой гибкости. Вместо нее можно в выражениях поиска можно использовать символы маски, как показано в следующемразделе.Символы маскиПри поиске частичных соответствий строк интерес могут представлять:• Строки, начинающиеся/заканчивающиеся определенным символом• Строки, начинающиеся/заканчивающиеся подстрокой• Строки, содержащие определенный символ в любом месте строки• Строки, содержащие подстроку в любом месте строки• Строки определенного формата, независимо от входящих в них отдельных символовС помощью символов маски, представленных в табл.
4.4, можно построить выражения для поиска этих и многих других частичных строковых соответствий.Таблица 4.4. Символы маскиСимвол маскиСоответствие_Точно один символ%Любое число символов (в том числе ни одного)Символ подчеркивания замещает один символ, а символ процента может замещать разное количество символов.
При построении условий,использующих выражения поиска, применяется оператор like (как):mysql> SELECT lname84Глава 4. Фильтрация> FROM employee> WHERE lname LIKE '_a%e%';++| lname|++| Barker|| Hawthorne || Parker|| Jameson |++4 rows in set (0.00 sec)Выражение поиска в предыдущем примере определяет строки, содержащие «а» во второй позиции, за которым следует «е» в любом другомместе строки (включая последний символ). В табл. 4.5 показано ещенесколько выражений поиска и их интерпретации.Таблица 4.5.
Примеры выражений поискаВыражение поиска ИнтерпретацияF%Строки, начинающиеся с «F»%tСтроки, заканчивающиеся на «t»%bas%Строки, содержащие подстроку «bas»_ _t_Строки, состоящие из четырех символов с «t» в третьейпозиции_ _ __ __ _ _ _Строки из 11 символов, где четвертый и седьмой символы – дефисыПоследний пример из табл. 4.5 можно использовать для поиска клиентов, федеральный ID которых соответствует формату, используемомудля номеров социальной страховки:mysql> SELECT cust_id, fed_id> FROM customer> WHERE fed_id LIKE '_ _ __ __ _ _ _';+++| cust_id | fed_id|+++|1 | 111111111 ||2 | 222222222 ||3 | 333333333 ||4 | 444444444 ||5 | 555555555 ||6 | 666666666 ||7 | 777777777 ||8 | 888888888 ||9 | 999999999 |+++9 rows in set (0.02 sec)Типы условий85Символы маски хороши для простых выражений поиска.