| СТАТЬЯ | 02.08.01 | 
Структуризированный язык запросов (SQL)
В синтаксисе фразы WHERE (п.2.1) показано, что для отбора нужных строк таблицы можно использовать операторы сравнения = (равно), <> (не равно), < (меньше), <= (меньше или равно), > (больше), >= (больше или равно), которые могут предваряться оператором NOT, создавая, например, отношения "не меньше" и "не больше".
Так, для получения перечня продуктов, практически не содержащих углеводов, можно сформировать запрос
SELECT Продукт, Белки, Жиры, Углев, K, Ca, Na, B2, PP, C FROM Продукты WHERE Углев = 0;
и получить:
| Продукт | Белки | Жиры | Углев | K | Ca | Na | B2 | PP | C | 
|---|---|---|---|---|---|---|---|---|---|
| Говядина | 189. | 124. | 0. | 3150 | 90 | 600 | 1.5 | 28. | 0 | 
| Судак | 190. | 80. | 0. | 1870 | 270 0 | 1.1 | 10. | 30 | 
Возможность использования нескольких условий, соединенных логическими операторами AND, OR, AND NOT и OR NOT, позволяет осуществить более детальный отбор строк. Так, для получения перечня продуктов, практически не содержащих углеводов и натрия, можно сформировать запрос:
SELECT Продукт, Белки, Жиры, Углев, K, Ca, Na, B2, PP, C FROM Продукты WHERE Углев = 0 AND Na = 0;
Результат запроса имеет вид
| Продукт | Белки | Жиры | Углев | K | Ca | Na | B2 | PP | C | 
|---|---|---|---|---|---|---|---|---|---|
| Судак | 190. | 80. | 0. | 1870 | 270 | 0 | 1.1 | 10. | 30 | 
Добавим к этому запросу еще одно условие
SELECT Продукт, Белки, Жиры, Углев, K, Ca, Na, B2, PP, C FROM Продукты WHERE Углев = 0 AND Na = 0 AND Продукт <> 'Судак';
и получим на экране сообщение "No rows exist or satisfy the specified clause" или аналогичное (в зависимости от вкусов разработчиков разных СУБД), информирующее об отсутствии строк, удовлетворяющих заданному(ым) условию(ям).
С помощью BETWEEN ... AND ... (находится в интервале от ... до ...) можно отобрать строки, в которых значение какого-либо столбца находятся в заданном диапазоне.
Например, выдать перечень продуктов, в которых значение содержания белка находится в диапазоне от 10 до 50:| Результат: | ||
|---|---|---|
| SELECT Продукт, Белки FROM Продукты WHERE Белки BETWEEN 10 AND 50; | ||
| Продукт | Белки | |
| Майонез | 31. | |
| Сметана | 26. | |
| Молоко | 28. | |
| Морковь | 13. | |
| Лук | 17. | |
Можно задать и NOT BETWEEN (не принадлежит диапазону между), например:
| Результат: | |||
|---|---|---|---|
| SELECT Продукт, Белки, Жиры FROM Продукты WHERE Белки NOT BETWEEN 10 AND 50 AND Жиры > 100; | |||
| Продукт | Белки | Жиры | |
| Говядина | 189. | 124. | |
| Масло | 60. | 825. | |
| Яйца | 127. | 115. | |
BETWEEN особенно удобен при работе с данными, задаваемыми интервалами, начало и конец которых расположен в разных столбцах.
Для примера воспользуемся таблицей "минимальных окладов" (табл. 2.1), величина которых непосредственно связана со студенческой стипендией. В этой таблице для текущего значения минимального оклада установлена запредельная дата окончания 9 сентября 9999 года.
Таблица 2.1 Минимальные оклады
| Миноклад | Начало | Конец | 
|---|---|---|
| 2250 | 01-01-1993 | 31-03-1993 | 
| 4275 | 01-04-1993 | 30-06-1993 | 
| 7740 | 01-07-1993 | 30-11-1993 | 
| 14620 | 01-12-1993 | 30-06-1994 | 
| 20500 | 01-07-1994 | 09-09-9999 | 
Если, например, потребовалось узнать, какие изменения минимальных окладов производились в 1993/94 учебном году, то можно выдать запрос
SELECT Начало, Миноклад FROM Миноклады WHERE Начало BETWEEN '1-9-1993' AND '31-8-1994'и получить результат:
| Начало | Миноклад | 
|---|---|
| 01-12-1993 | 14620 | 
| 01-07-1994 | 20500 | 
Отметим, что при формировании запросов значения дат следует заключать в апострофы, чтобы СУБД не путала их с выражениями и не пыталась вычитать из 31 значение 8, а затем 1994.
Для выявления всех значений минимальных окладов, которые существовали в 1993/94 учебном году, можно сформировать запрос
SELECT * FROM Миноклады WHERE Начало BETWEEN '1-9-1993' AND '31-8-1994' OR Конец BETWEEN '1-9-1993' AND '31-8-1994'
| Миноклад | Начало | Конец | 
|---|---|---|
| 7740 | 01/07/1993 | 30/11/1993 | 
| 14620 | 01/12/1993 | 30/06/1994 | 
| 20500 | 01/07/1994 | 09/09/9999 | 
Наконец, для получения минимального оклада на 15-5-1994:
| Результат: | ||
|---|---|---|
| SELECT Миноклад FROM Миноклады WHERE '15-05-1994' BETWEEN Начало AND Конец | ||
| Миноклад | ||
| 14620 | ||
Выдать сведения о блюдах на основе яиц, крупы и овощей
SELECT * FROM Блюда WHERE Основа IN (Яйца Крупа Овощи);
Результат:
| БЛ | Блюдо | В | Основа | Выход | Труд | 
|---|---|---|---|---|---|
| 1 | Салат летний | З | Овощи | 200. | 3 | 
| 3 | Салат витаминный | З | Овощи | 200. | 4 | 
| 16 | Драчена | Г | Яйца | 180. | 4 | 
| 17 | Морковь с рисом | Г | Овощи | 260. | 3 | 
| 19 | Омлет с луком | Г | Яйца | 200. | 5 | 
| 20 | Каша рисовая | Г | Крупа | 210. | 4 | 
| 21 | Пудинг рисовый | Г | Крупа | 160. | 6 | 
| 23 | Помидоры с луком | Г | Овощи | 260. | 4 | 
Рассмотренная форма IN является в действительности просто краткой записью последовательности отдельных сравнений, соединенных операторами OR. Предыдущее предложение эквивалентно такому:
SELECT * FROM Блюда WHERE Основа=Яйца OR Основа=Крупа OR Основа=Овощи;
Можно задать и NOT IN (не принадлежит), а также возможность использования IN (NOT IN) с подзапросом (см. главу 3).
Выдать перечень салатов
| Результат: | ||
|---|---|---|
| SELECT Блюдо FROM Блюда WHERE Блюдо LIKE 'Салат%'; | ||
| Блюдо | ||
| Салат летний | ||
| Салат мясной | Салат витаминный | |
| Салат рыбный | ||
Обычная форма "имя_столбца LIKE текстовая_константа" для столбца текстового типа позволяет отыскать все значения указанного столбца, соответствующие образцу, заданному "текстовой_константой". Символы этой константы интерпретируются следующим образом:
Следовательно, в приведенном примере SELECT будет осуществлять выборку записей из таблицы Блюда, для которых значение в столбце Блюдо начинается сочетанием 'Салат' и содержит любую последовательность из нуля или более символов, следующих за сочетанием 'Салат'. Если бы среди блюд были "Луковый салат", "Фруктовый салат" и т.п., то они не были бы найдены. Для их отыскания надо изменить фразу WHERE:
WHERE Блюдо LIKE '%салат%'
или при отсутствии различий между малыми и большими буквами (такую настройку допускают некоторые СУБД):
WHERE Блюдо LIKE '%Салат%'
Это позволит отыскать все салаты.
Как было рассказано в п.2.2.3, если при загрузке данных не введено значение в какое-либо поле таблицы, то СУБД поместит в него NULL-значение. Аналогичное значение можно ввести в поле таблицы, выполняя операцию изменения данных. Так, при отсутствии сведений о наличии у поставщиков судака и моркови в столбцы Цена и К_во соответствующих строк таблицы Поставки вводится NULL и там будет храниться код NULL-значения, а не 0, 0. или пробел. (Отметим, что в распечатке таблицы Поставки рис.1.1 в этих местах расположен пробел, установленный в СУБД для представления NULL-значения при выводе на печать).
В этом случае для выявления названий продуктов, отсутствующих в кладовой, шеф-повар может дать запрос
| Результат: | ПР | |
|---|---|---|
| SELECT DISTINCT ПР FROM Наличие WHERE К_во IS NULL; | 2 9 | |
Естественно, что для выявления продуктов, существующих в кладовой, следует дать запрос
SELECT DISTINCT ПР FROM Наличие WHERE К_во IS NOT NULL;
Использование условий
столбец IS NULL и столбец IS NOT NULL
вместо, например,
столбец = NULL и столбец <> NULL
связано с тем, что ничто - и даже само NULL-значение - не считается равным другому NULL-значению. (Несмотря на это, два неопределенных значения рассматриваются, однако, как дубликаты друг друга при исключении дубликатов, и предложение SELECT DISTINCT даст в результате не более одного NULL-значения.)
Синтаксис фразы упорядочения был дан в п. 2.1. Простейший вариант этой фразы - упорядочение строк результата по значению одного из столбцов с указанием порядка сортировки или без такого указания. (По умолчанию строки будут сортироваться в порядке возрастания значений в указанном столбце.)
Например, выдать перечень продуктов и содержание в них основных веществ в порядке убывания содержания белка
| Результат: | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 
 | 
 | |||||||||||||||||||||||||||||||||
При включении в список ORDER BY нескольких столбцов СУБД сортирует строки результата по значениям первого столбца списка пока не появится несколько строк с одинаковыми значениями данных в этом столбце. Такие строки сортируются по значениям следующего столбца из списка ORDER BY и т.д.
Например, выдать содержимое таблицы Блюда, отсортировав ее строки по видам блюд и основе:
| Результат: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 
 | 
 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Кроме того, в список ORDER BY можно включать не только имя столбца, а его порядковую позицию в перечне SELECT. Благодаря этому возможно упорядочение результатов на основе вычисляемых столбцов, не имеющих имен.
Например, запрос
SELECT Продукт, ((Белки+Углев)*4.1+Жиры*9.3) FROM Продукты ORDER BY 2;
позволит получить список продуктов, показанный на рис.2.2,в – переупорядоченный по возрастанию значений калорийности список рис.2.2,а.
В SQL существует ряд специальных стандартных функций (SQL-функций). Кроме специального случая COUNT(*) каждая из этих функций оперирует совокупностью значений столбца некоторой таблицы и создает единственное значение, определяемое так:
Для функций SUM и AVG рассматриваемый столбец должен содержать числовые значения.
Следует отметить, что здесь столбец - это столбец виртуальной таблицы, в которой могут содержаться данные не только из столбца базовой таблицы, но и данные, полученные путем функционального преобразования и (или) связывания символами арифметических операций значений из одного или нескольких столбцов. При этом выражение, определяющее столбец такой таблицы, может быть сколь угодно сложным, но не должно содержать SQL-функций (вложенность SQL-функций не допускается). Однако из SQL-функций можно составлять любые выражения.
Аргументу всех функций, кроме COUNT(*), может предшествовать ключевое слово DISTINCT (различный), указывающее, что избыточные дублирующие значения должны быть исключены перед тем, как будет применяться функция. Специальная же функция COUNT(*) служит для подсчета всех без исключения строк в таблице (включая дубликаты).
Если не используется фраза GROUP BY, то в перечень элементов_SELECT можно включать лишь SQL-функции или выражения, содержащие такие функции. Другими словами, нельзя иметь в списке столбцы, не являющихся аргументами SQL-функций.
Например, выдать данные о массе лука (ПР=10), проданного поставщиками, и указать количество этих поставщиков:
| Результат: | ||
|---|---|---|
| SELECT SUM(К_во),COUNT(К_во) FROM Поставки WHERE ПР = 10; | ||
| SUM(К_во) | COUNT(К_во) | |
| 220 | 2 | |
Если бы для вывода в результат еще и номера продукта был сформирован запрос
SELECT ПР,SUM(К_во),COUNT(К_во) FROM Поставки WHERE ПР = 10;
то было бы получено сообщение об ошибке. Это связано с тем, что SQL-функция создает единственное значение из множества значений столбца-аргумента, а для "свободного" столбца должно быть выдано все множество его значений. Без специального указания (оно задается фразой GROUP BY) SQL не будет выяснять, одинаковы значения этого множества (как в данном примере, где ПР=10) или различны (как было бы при отсутствии WHERE фразы). Поэтому подобный запрос отвергается системой.
Правда, никто не запрещает дать запрос
SELECT 'Кол-во лука =',SUM(К_во),COUNT(К_во) FROM Поставки WHERE ПР = 10;
| Результат: | ||
|---|---|---|
| 'Кол-во лука =' | SUM(К_во) | COUNT(К_во) | 
| Кол-во лука = | 220 | 2 | 
Отметим также, что в столбце-аргументе перед применением любой функции, кроме COUNT(*), исключаются все неопределенные значения. Если оказывается, что аргумент - пустое множество, функция COUNT принимает значение 0, а остальные - NULL.
Например, для получения суммы цен, средней цены, количества поставляемых продуктов и количества разных цен продуктов, проданных коопторгом УРОЖАЙ (ПС=5), а также для получения количества продуктов, которые могут поставляться этим коопторгом, можно дать запрос
SELECT SUM(Цена),AVG(Цена),COUNT(Цена), COUNT(DISTINCT Цена),COUNT(*) FROM Поставки WHERE ПС = 5;
и получить
| SUM(Цена) | AVG(Цена) | COUNT(Цена) | COUNT(DISTINCT Цена) | COUNT | 
|---|---|---|---|---|
| 6.2 | 1.24 | 5 | 4 | 7 | 
В другом примере, где надо узнать "Сколько поставлено моркови и сколько поставщиков ее поставляют?":
SELECT SUM(К_во),COUNT(К_во) FROM Поставки WHER ПР = 2;
будет получен ответ:
| SUM(К_во) | COUNT (К_во) | 
|---|---|
| -0- | 0 | 
Наконец, попробуем получить сумму массы поставленного лука с его средней ценой ("Сапоги с яичницей"):
| Результат: | |
|---|---|
| SELECT (SUM(К_во) +AVG(Цена)) FROM Поставки WHERE ПР = 10; | |
| SUM(К_во)+AVG(Цена) | |
| 220.6 | 
Дополнительную информацию Вы можете получить в компании Interface Ltd.
  
  Отправить ссылку на страницу по e-mail
  Обсудить на форуме Oracle 
| Interface Ltd. Отправить E-Mail http://www.interface.ru | |
| Ваши 
      замечания и предложения отправляйте 
      автору По техническим вопросам обращайтесь к вебмастеру Документ опубликован: 02.08.01 |