- •Оператор select
- •Простейший вид оператора select
- •Использование предложения where
- •Внутреннее соединение таблиц
- •Использование псевдонимов таблиц
- •Предложение order by - определение сортировки
- •Устранение повторяющихся значений
- •Расчет значений вычисляемых столбцов
- •Агрегатные функции
- •Группировка записей
- •Задание сложных условий поиска
- •Использование подзапросов
- •Дополнительные возможности использования подзапросов, возвращающих единичное значение
- •Использование подзапросов, возвращающих множество значений
- •Внешние соединения
- •Union - объединение результатов выполнения нескольких операторов select
Задание сложных условий поиска
Ранее были рассмотрены простые варианты задания условия поиска в предложении WHERE (сравнение столбца с константой и внутреннее соединение). Однако эти условия могут быть достаточно сложными, чему способствует и сам синтаксис оператора SELECT. Рассмотрим основные конструкции для построения сложных условий поиска.
Сложные логические выражения строятся при помощи операторов AND, OR и NOT. Их использование, а также построение из них сложных выражений подчиняется стандартным правилам, принятым для большинства алгоритмических языков (в том числе - в Object Pascal), с одним важным исключением: операции отношения в них имеют больший приоритет, чем логические операции, что избавляет от необходимости расстановки многочисленных скобок.
В следующем запросе будут получены все записи из таблицы RASHOD, причем для каждого товара будет указана его цена из таблицы TOVARY, а для каждого покупателя - город из таблицы POKUPATELI:
SELECT R.*, T.ZENA, P.ADRES
FROM RASHOD R, TOVARY T, POKUPATELI P
WHERE R.TOVAR = T.TOVAR AND R.POKUP = P.POKUP
Пример. Получить все записи из таблицы RASHOD, для которых указано имя покупателя, плюс соответствующую каждому товару цену из таблицы TOVARY. При этом количество отпущенного товара должно быть не больше 30 или не меньше 3000 единиц:
SELECT R.*, T.ZENA FROM RASHOD R, TOVARY T WHERE R.TOVAR = T.TOVAR AND (R.KOLVO <= 30 OR R.KOLVO >= 3000) AND
R.POKUP IS NOT NULL ORDER BY R.KOLVO
Пример. Показать сведения обо всех отпусках товара, в которых количество отпущенного товара (в единицах) равно 100, 1000 или 3000:
SELECT * FROM RASHOD WHERE KOLVO IN (100, 1000, 3000)
Пример. Получить список товаров, начинающихся с буквы «С» (рис. 23.27):
SELECT * FROM TOVARY WHERE TOVAR STARTING WITH "C"
Использование подзапросов
Часто невозможно решить поставленную задачу путем использования единственного запроса. Например, в тех случаях, когда при использовании условия поиска
<сравниваемое значение> <оператор> <значение, с которым сравнивать>
в предложении WHERE параметр <зшчение, с которым сравнивать> заранее не определен и должен вычисляться в момент выполнения оператора SELECT или представляет собой не одно, а несколько значений.
В такого рода случаях используются подзапросы (вложенные запросы). Оператор SELECT с подзапросом имеет такой вид:
SELECT ...
FROM ...
WHERE <сравниваемое значение> <оператор> (SELECT ...)
Синтаксис вложенного запроса ничем не отличается от синтаксиса основного запроса, и, следовательно, вложенный запрос может, в свою очередь, содержать подзапрос. Заметим, что синтаксис сервера InterBase/Firebird требует заключать подзапрос в круглые скобки.
Следующий запрос возвращает дату, на которую приходится максимальный отпуск товаров:
SELECT KOLVO, DAT_RASH
FROM RASHOD
WHERE KOLVO=(SELECT MAX(KOLVO)FROM RASHOD)
Усложним предыдущий пример. Определить дату, когда со склада было отгружено максимальное количество товара, и реквизиты покупателя, который этот товар купил:
SELECT R.KOLVO, R.DAT_RASH, P.POKUP, P.GOROD, P.ADRES FROM RASHOD R, POKUPATELI P WHERE (R.POKUP = P.POKUP) AND
KOLVO =(SELECT MAX(KOLVO) FROM RASHOD)
По сравнению с предыдущим примером в запрос включено внутреннее соединение таблиц RASHOD и POKUPATELI
Замечание. Распространенной ошибкой является использование вложенного оператора SELECT, который вместо единичного значения способен возвращать список значений.
Как уже говорилось, синтаксис вложенного запроса ничем не отличается от синтаксиса основного запроса, что означает возможность вложения в подзапрос своего подзапроса, в тот - своего и т. д. Эта возможность широко используется на практике.
Пример. Составим список отгрузки товаров покупателю, который в свое время купил максимальную партию какого-либо товара:
SELECT RRR.* FROM RASHOD RRR WHERE RRR.POKUP IN
(SELECT R.POKUP FROM RASHOD R WHERE KOLVO =
(SELECT MAX(RSH.KOLVO) FROM RASHOD RSH))
Поясним логический порядок выполнения запроса. Сначала определяется самая крупная покупка - отыскивается максимальное значение в столбце KOLVO («самый вложенный» подзапрос SELECT MAX). Далее в «среднем» подзапросе SELECT R.POKUP определяется покупатель, осуществивший эту покупку, а затем основной запрос SELECT RRR выбирает все записи с найденным покупателем.