Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Методичка по информатике

.pdf
Скачиваний:
160
Добавлен:
27.03.2016
Размер:
2.58 Mб
Скачать

отбора записей, или в инструкции Select в качестве вычисляемого выражения. Весь подчиненный запрос заключается в скобки в любом месте его применения.

Существует три варианта синтаксиса для подчиненных запросов в инструкции Where:

Where <поле или выражение><операции сравнения>[ Any | All ]( Select … )

Where <поле или выражение> [ NOT] IN (Select … )

Where [ NOT] EXISTS(Select … )

1.4.3.9.1 Использование подчиненного запроса с операциями сравнения

Использование подчиненного запроса эквивалентно объединению с запросом. Подчиненные запросы легче для понимания, но они выполняются медленнее, чем объединение.

В первом синтаксисе подчиненный запрос возвращает одно или несколько или все значения одного столбца. В инструкции Where происходит сравнение какого либо поля или выражения с возвращаемым значением. Если подзапрос возвращает несколько значений то должны использоваться предикаты Any, Some или All.

Например, задача, в которой необходимо вывести все агентства с максимальным количеством проданных путевок, может быть решена с помощью функции Dmax( запрос Z**), с помощью сортировки с предикатом Top (запрос Z**), но так же с подзапросом Z54. Запрос Z54 для решения поставленной задачи будет следующим:

Select Agen.* From Agen

Where Kolpt = (Select Max(Kolpt) From Agen);

Результат этого запроса представлен на рисунке 1.4.3.9.1.1.

Рис. 1.4.3.9.1.1 Результат запроса Z54.

В нашем примере подзапрос вычисляет одно значение – максимальное из столбца Kolp, а инструкция Where отбирает записи, для которых это поле имеет максимальное значение. Другое решение этой задачи можно получить, если подзапрос будет возвращать все значения столбца Kolp. Предикат All позволит выбирать записи, для которых значение столбца больше или равно

всем.

Select Agen.* From Agen

Where Kolpt >= All (Select Kolp From Agen);

Результат буде таким же, как и у запроса Z54.

101

Предикат Any в подзапросе, возвращающем несколько значений или все значения столбца, позволит выбрать все записи, кроме имеющих максимальное значение. Запрос, решающий такую задачу Z56 будет иметь следующий текст:

Select Agen.* From Agen

Where Kolpt < Any (Select Kolpt From Agen);

Результат этого запроса представлен на рисунке 1.4.3.9.1.2.

Рис. 1.4.3.9.1.2 Результат запроса Z56

Если в предыдущем запросе выводились записи с максимальным значением поля Kolpt, то в результате этого запроса Z56. выводятся все записи, кроме тех, которые содержат максимальное значение этого поля.

Используя подчиненный запрос, можно решить задачу вывода невостребованных туров. Эта задача уже была решена ранее запросом Z53. Таким запросом будет Z57, представленный следующим текстом:

Select * From Tyr

Where Sht <> ALL (Select Sht From Agen);

Результат представлен на рисунке 1.4.3.9.1.3.

Рис. 1.4.3.9.1.3 Результат запроса Z57

102

Подчиненный запрос может вычислять любую итоговую функцию по любому столбцу. Вычисленное значение может быть выведено в инструкции Select. Это имеет смысл, если вычисляется, например, среднее арифметическое значение. Например, вычислим среднюю стоимость купленных путевок каждым агентством, и выведем агентства, туры и страны со стоимостью больше среднего значения. Запрос Z58 будет следующим:

Select Agn,Tyr.Sht,Str,Kolpt*CenAs Stm, (Select Avg(Kolpt*Cen) As Sred From Tyr Inner Join Agen On Tyr.Sht=Agen.Sht

Where Kolpt*Cen > (Select Avg(Kolpt*Cen)From Tyr Inner Join Agen On

Tyr.Sht=Agen.Sht );

В этом запросе мы используем поля двух связанных таблиц, так как для совпадающих ключей мы вычисляем стоимость реализованных путевок Stm ( Kolpt*Cen ) и из них же вычисляем среднюю стоимость Sred с помощью подчиненного запроса. Это вычисленное подзапросом значение Sred можно отредактировать для вывода. Например, вывести среднее значение стоимости реализованных путевок Sred с двумя знаками после точки. Редактирование вычисляемых запросом полей можно осуществлять только в режиме конструктора. В режиме конструктора можно выделить вычисляемый столбец Sred и открыть для него окно свойств ( Свойства поля). Для свойства поля – «формат поля»-выбрать значение Фиксированный. В свойстве поля – число десятичных знаков – выбрать значение 2. Вид окна свойств в режиме конструктора представлен на рисунке 1.4.3.9.1.4.

Рис. 1.4.3.9.1.4 Вид окна свойств поля запроса.

103

Чтобы вывести вычисленное среднее значение, мы размещаем подзапрос в инструкции Select основного запроса. Это - среднее значение по всем записям, и оно выводится в каждой записи результирующего набора. Подзапрос используется и в критерии отбора записей, поэтому записывается дважды.

Результат запроса Z58 представлен на рисунке 1.4.3.9.1.5.

Рис. 1.4.3.9.1.5 Результат запроса Z58.

Среднее значение Sred вывели для большей наглядности результата.

1.4.3.9.2 Использование подчиненного запроса с оператором IN

Часто возникает необходимость сравнить значение определенного столбца таблицы со списком значений из другой таблицы или запроса. Например, можно вывести страну, шифр тура, количество дней и цену для таких туров, которые были проданы в количестве более двенадцати. Это можно сделать с помощью подчиненного запроса в запросе Z59, записанного следующим оператором SQL:

Select Tyr.*

From Tyr

Where Sht IN (Select Sht From Agen Where Kolpt>12);

Такой подчиненный запрос должен возвращать набор записей только из одного столбца. Если в подчиненном запросе более одного столбца, Access выдает сообщение об ошибке. Альтернативным запросом, решающим эту же задачу является запрос на объединение.

Select Distinct Tyr.*

From Tyr Inner Join Agen On Tyr.Sht=Agen.Sht Where Kolpt >12;

Оба запроса дают одинаковый результат, но запрос с подзапросом более простой для восприятия. Результаты этих запросов одинаковые и один из них Z59 представлен на рисунке 1.4.3.9.2.1.

104

Рисунок 1.4.3.9.2.1 Результат запроса Z59

Логическая операция IN с подчиненным запросом может использоваться с операцией Not для отбора тех строк, которых нет в списке значений, возвращаемых подчиненным запросом. Например, вывести информацию о турах с количеством проданных путевок не более двенадцати. Запрос легко получить из предыдущего запроса Z59. Изменим его, поставив операцию Not перед операцией IN. Получим запрос Z60, имеющим следующий вид:

Select Tyr.* From Tyr

Where Sht Not IN (Select Sht From Agen Where Kolpt>12);

Результат запроса Z60 представлен на рисунке 1.4.3.9.2.2.

Рис. 1.4.3.9.2.2 Результат запроса Z60

1.4.3.9.3 Использование подчиненного запроса с оператором Exists

Операция Exists проверяет подчиненный запрос на наличие или отсутствие записей, возвращаемых этим запросом. Результат этой операции True, если подчиненный запрос возвращает какие – либо строки, иначе ее значение False. Количество столбцов в подчиненном запросе не имеет значения. Операция Exists может использоваться с операцией Not для проверки противоположных условий. Подчиненный запрос, используемый с операцией Exists всегда должен быть связан с внешним запросом, то есть быть коррелированным.

105

Например, с помощью подзапроса можно вывести невостребованные туры, то есть те, шифры которых отсутствуют в таблице Agen. Эта задача решалась запросом на объединение Z53. Наш запрос Z62 будет следующим:

Select Tyr.* From Tyr

Where Not Exists (Select * From Agen Where Sht=Tyr.Sht);

Ссылка на внешний запрос осуществляется в инструкции Where в условии отбора записей Sht=Tyr.Sht.

Результат запроса Z62 представлен на рисунке 1.4.3.9.3.1.

Рис. 1.4.3.9.3.1 Результат запроса Z62.

В этом запросе для каждой записи внешнего запроса выполняется подчиненный запрос. Эсли подзапрос содержит хотя бы одну запись, операция Exists дает истинное значение. Так как в таблице Agen нет записей о турах на Кипр, то при шифрах 220 и 234 подзапрос не возвращает ни одной записи, и значением операции Exists для эти шифров будет False, а Not Exists True.

1.4.3.10 Создание запросов на основе других запросов

Запросы можно использовать как источник данных для других запросов. Такая необходимость иногда возникает, если нет возможности решить задачу с помощью подчиненных запросов. Например, требуется подсчитать количество различных агентств. Названия агентств находятся только в таблице Agen, но они там много раз повторяются и итоговая функция Count подсчитает количество записей, которое не соответствует количеству агентств. Можно создать запрос, в котором агентства не повторяются. Таким запросом может быть запрос, выводящий список различных агентств (запрос типа запроса Z10) Получить его можно, сохранив SQL оператор запроса Z10 и изменив в нем источник данных на Agen и список вывода на Agn в операторе Select . Получим запрос Z63 следующего вида:

Select Distinct Agn From Agen;

Его результатом будет следующий рисунок (1.4.3.10.1).

106

Рис. 1.4.3.10.1 Результат запроса Z63

Если в таком запросе подсчитать количество записей, то получим решение нашей задачи, то есть количество различных агентств. Для этого запишем запрос Z64.

Select Count(*) As KolAgn From Z63;

Результат запроса – значение поля KolAgn, созданного запросом Z64, представлено на рисунке 1.4.3.10.2.

Рис. 1.4.3.10.2. Результат запроса Z64.

Другой задачей, в которой источником данных должен быть запрос, может быть задача вывода всей информации об агентствах и турах с максимальной продажей путевок по каждому агентству. Для решения этой задачи сначала составляется запрос, вычисляющий по каждому агентству максимальное количество проданных путевок (Z65 с полями AGN и MaxPt). Затем, в объединенном запросе по двум таблицам и запросу Z65 выводятся те записи двух таблиц, для которых выполняются условия: количество проданных путевок максимальное (kOLPT=Z65.MAXpT), а названия агентств в запросе Z65 и в объединенном запросе совпадают (AGEN.AGN=Z65.AGN). Первый из этих запросов (Z65) имеет следующий вид:

SELECT AGN, Max(Kolpt) AS MaxPt FROM AGEN

GROUP BY AGN;

Его результат представлен на рисунке 1.4.3.10.3.

Рис. 1.4.3.10.3 Результат запроса Z65

107

Текст основного запроса (Z66) будет следующим:

SELECT Agen.Agn, Agen.Sht, Str, dt, kold, Cen, MaxKolpt

FROM z65, agen INNER JOIN Tyr ON Tyr.Sht=Agen.Sht

WHERE kOLPT=z65.MAXpT And agen.AGN=z65.AGN

ORDER BY Agen.Agn;

В этом запросе Z66 одинаковые поля названий агентств AGN в таблице Agen и в запросе Z65 совпадают, поэтому берутся с уточнением из какого источника. Результат запроса представлен на рисунке 1.4.3.10.3.

Рис. 1.4.3.10.3 Результат запроса Z66

1.4.3.11. Перекрестные запросы

Перекрестный запрос - это особый тип итогового запроса. Он имеет вид таблицы типа Exel, в которой по двум объектам вычисляются и выводятся итоги. Один из этих объектов определяет строки, другой – столбцы, а на пересечении строк и столбцов располагаются вычисляемые итоги. Это могут быть любые итоговые функции. Перекрестный запрос может строиться по одной таблице или быть одновременно запросом на объединение. Синтаксис перекрестного запроса следующий:

Transform <итоговые функции>

Select <заголовки строк и итоги по строкам> From <источник данных>

Group by <заголовки строк> Pivot <заголовки столбцов>;

В этом операторе в инструкции Transform указывается одна функция, результат которой будет располагаться на пересечении строк и столбцов. В инструкции Select указывается имя поля, по которому осуществляется группировка по строке. Это же имя должно быть указано в инструкции Group by. Но в инструкции Select можно дополнительно указать любые итоговые функции, которые будут вычисляться по полю группировки. В инструкции Pivot указываются поля, выражения или константы, которые будут заголовками столбцов. Итоги вычисляются по стокам и столбцам. Например, для нашей первой таблице (Firm) с помощью перекрестного запроса можно решить такую задачу, как по каждому изделию и по каждому предприятию

108

вывести общий годовой выпуск. Но в нашей таблице по каждому предприятию дан один годовой выпуск одного изделия. Значит итоговая сумма (или другая функция) на пересечении – это сумма из одного значения. Добавим еще два показателя по каждому изделию: суммарный годовой выпуск и количество фирм выпускающих изделие.

Для такой таблицы заголовками строк являются названия изделия (), суммарный годовой впуск() и количество фирм(). Заголовками столбцов будут названия фирм(). Запрос Z67 должен быть следующим:

Transform Sum(God) As Sum-God

Select Izd,Sum(god) as SumGod,Count(*) as KolFirm

From Firm

Group by Izd

Pivot Nazf;

Результат запроса Z67 на рисунке 1.4.3.11.1.

Рис. 1.4.3.11.2 Результат запроса Z67

Перекрестный запрос по двум таблицам позволит вывести информацию по странам и агентствам о количестве проданных туров каждым агентством в каждую страну, одновременно можно подсчитать общее количество путевок, проданных в каждую страну, и количество туров по станам. Запрос Z68 будет следующим:

Transform Sum(Kolpt)

Select Str,Count(*) as Koltyr ,Sum(Kolpt) as SumKolpt

From Tyr Iner Join Agen On Tyr.Sht = Agen.Sht

Group by Str Pivot Agen;

Результат запроса представлен на рисунке 1.4.3.11.2.

Рис. 1.4.3.11.2 Результат запроса Z68

109

Спомощью перекрестного запроса можно получить картину распределения продажи путевок каждым агентством по месяцам. Для этого воспользуемся стандартными функциями обработки дат:

Month(дата) – позволяет выделить номер месяца из даты. Year (дата) - позволяет выделить номер года из даты. Day(дата) - позволяет выделить день месяца из даты.

Спомощью функции Format можно получить из даты названия месяца. Для этого в функции Format записывается шаблоны для вывода месяца “mmm” . Запрос Z69 будет следующим:

Transform Sum(Kolpt)

Select Agn,Count(*) as Koltyr

From Tyr Iner Join Agen On Tyr.Sht = Agen.Sht

Group by Agn

Pivot Format(dt,”mmm”) ;

Вэтом запросе в качестве заголовка строк берем названия агентств Agn,

ав качестве заголовка столбцов – дату продажи dt, из которой формируем название месяца. На пересечении строк и столбцов вычисляем суммы продаж, так как в один месяц одной фирмой были проданы путевки по разным турам. Дополнительно по каждому агентству мы вычисляем общее количество туров. Результат запроса представлен на рисунке 1.4.3.11.3.

Рис. 1.4.3.11.3 Результат запроса Z69.

Контрольные вопросы

1.Как задается Структура базы данных (включая связи между таблицами)?

2.Что такое запрос на выборку значений?

3.Какие виды запросов модифицируют данные в базе данных?

4.Как задаются ограничения выборки данных (отбираются нужные записи)?

5.Как определить параметры запроса?

Лабораторная работа № 1.4.1

Тема: Применение системы управления базами данных для ввода, хранения и обработки пользовательской информации Цель работы: Изучить инструментарий СУБД, создать пользовательскую БД

110